├── Manual └── TSX2StaMPS_Tutorial_SNAP2Stamps_v21.docx ├── graphs ├── stripmap_Export.xml ├── topsar_export.xml ├── stripmap_TSX_Subset.xml ├── stripmap_plot_ifg.xml ├── plot_amplitude.xml ├── stripmap_plot_coreg.xml ├── stripmap_plot_split.xml ├── stripmap_DEM_Assisted_Coregistration.xml ├── stripmap_DEM_Assisted_Coregistration_extDEM.xml ├── topsar_master_split_applyorbit.xml ├── topsar_secondaries_split_applyorbit.xml ├── plot_phase.xml ├── topsar_plot_amplitude_deburst.xml ├── stripmap_Interferogram_TopoPhase_extDEM.xml ├── topsar_master_assemble_split_applyorbit.xml ├── topsar_secondaries_assemble_split_applyorbit.xml ├── stripmap_Interferogram_TopoPhase.xml ├── topsar_export_mergeIW_subset.xml ├── topsar_export_mergeIW_subset_extDEM.xml ├── topsar_coreg_ifg_computation_noESD.xml ├── topsar_coreg_ifg_computation_noESD_extDEM.xml ├── topsar_coreg_ifg_computation.xml ├── topsar_coreg_ifg_computation_extDEM.xml ├── topsar_coreg_ifg_computation_subset_noESD.xml ├── topsar_coreg_ifg_computation_subset_noESD_extDEM.xml ├── topsar_coreg_ifg_computation_subset.xml └── topsar_coreg_ifg_computation_subset_extDEM.xml ├── bin ├── project_stripmap.conf ├── project_topsar.conf ├── topsar_step_0_secondaries_prep.py ├── stripmap_step_1b_masterselection.py ├── stripmap_step_0b_secondaries_prep.py ├── topsar_automaster.py ├── stripmap_step_0a_unpack_sar_scenes.py ├── auto_run.py ├── asf_s1_downloader.py ├── stripmap_step_5_stamps_export.py ├── stripmap_step_3_ifg_sar.py ├── stripmap_step_2_coreg_sar.py ├── stripmap_step_1_subset_sar.py ├── topsar_step_1_splitting_master_multi_IW.py ├── topsar_step_4_plotting_all.py ├── topsar_step_2_splitting_secondaries.py ├── topsar_step_5_stamps_export_multiIW.py └── topsar_step_3_coreg_ifg_topsar_smart.py ├── snap2stamps_environment.yml ├── README.md └── LICENSE.md /Manual/TSX2StaMPS_Tutorial_SNAP2Stamps_v21.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mdelgadoblasco/snap2stamps/HEAD/Manual/TSX2StaMPS_Tutorial_SNAP2Stamps_v21.docx -------------------------------------------------------------------------------- /graphs/stripmap_Export.xml: -------------------------------------------------------------------------------- 1 | 2 | 1.0 3 | 4 | StampsExport 5 | 6 | 7 | 8 | 9 | 10 | OUTPUTFOLDER 11 | true 12 | 13 | 14 | 15 | Read 16 | 17 | 18 | COREGFILE 19 | 20 | 21 | 22 | Read 23 | 24 | 25 | IFGFILE 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /graphs/topsar_export.xml: -------------------------------------------------------------------------------- 1 | 2 | 1.0 3 | 4 | StampsExport 5 | 6 | 7 | 8 | 9 | 10 | OUTPUTFOLDER 11 | true 12 | 13 | 14 | 15 | Read 16 | 17 | 18 | COREGFILE 19 | 20 | 21 | 22 | Read 23 | 24 | 25 | IFGFILE 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /graphs/stripmap_TSX_Subset.xml: -------------------------------------------------------------------------------- 1 | 2 | 1.0 3 | 4 | Read 5 | 6 | 7 | INPUTXML 8 | 9 | 10 | 11 | Subset 12 | 13 | 14 | 15 | 16 | 17 | 0,0,18621,34337 18 | POLYGON 19 | 1 20 | 1 21 | false 22 | 23 | true 24 | 25 | 26 | 27 | Write 28 | 29 | 30 | 31 | 32 | OUTPUTSUBSETFOLDER/OUTPUTFILE 33 | BEAM-DIMAP 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /bin/project_stripmap.conf: -------------------------------------------------------------------------------- 1 | ################## STRIPMAP CONFIGURATION FILE ###################### 2 | ##################################################################### 3 | [PROJECT_DEFINITION] 4 | PROJECTFOLDER = D:/project_newsoftwaretest #example projectfolder 5 | GRAPHSFOLDER = D:/project_newsoftwaretest/graphs #example graphsfolder 6 | ##################################################################### 7 | [PROC_OPTIONS] 8 | # Y / N OPTIONS 9 | OVERWRITE = N 10 | SMARTHDD = N 11 | PLOTTING = N 12 | ##################################################################### 13 | [PROC_PARAMETERS] 14 | # SENSOR: TSX / TDX 15 | SENSOR = TSX 16 | POLARISATION = HH 17 | MASTER = D:/project_newsoftwaretest/master/20220124_sub.dim #example master 18 | EXTDEM = C:/Users/Administrator/Desktop/KI4KI/Daten/4_DGM/All_Subset/dgm5m_4326_tsx_all.tif #example dem 19 | ##################################################################### 20 | [AOI_DEFINITION] 21 | # AOI_MODE OPTIONS: WKT / BBOX / SHP / KML / GeoJSON 22 | AOI_MODE = BBOX 23 | LONMIN = 7.43 24 | LATMIN = 51.20 25 | LONMAX = 7.57 26 | LATMAX = 51.28 27 | WKT = POLYGON((11.997 41.455,11.997 42.294,12.936 42.294,12.936 41.455,11.997 41.455)) 28 | AOI_FILE = /tmp/my_aoi.shp 29 | ##################################################################### 30 | [SNAP_GPT] 31 | SNAP_INSTALLATION_FOLDER = C:/Program Files/snap 32 | SNAP_HOME_DIR = C:/Program Files/snap/.snap 33 | ##################################################################### 34 | [COMPUTING_RESOURCES] 35 | CPU = 14 36 | CACHE = 118G 37 | ##################################################################### 38 | -------------------------------------------------------------------------------- /graphs/stripmap_plot_ifg.xml: -------------------------------------------------------------------------------- 1 | 2 | 1.0 3 | 4 | Read 5 | 6 | 7 | INPUTFILE 8 | 9 | 10 | 11 | BandMaths 12 | 13 | 14 | 15 | 16 | 17 | 18 | phase 19 | float32 20 | phase(QBAND,IBAND) 21 | 22 | 23 | 0.0 24 | 25 | 26 | 27 | 28 | 29 | 30 | Multilook 31 | 32 | 33 | 34 | 35 | phase 36 | 3 37 | 1 38 | false 39 | true 40 | 41 | 42 | 43 | Write 44 | 45 | 46 | 47 | 48 | OUTPUTFOLDER/OUTPUTNAME.dim 49 | BEAM-DIMAP 50 | 51 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /graphs/plot_amplitude.xml: -------------------------------------------------------------------------------- 1 | 2 | 1.0 3 | 4 | Read 5 | 6 | 7 | INPUTFILE 8 | 9 | 10 | 11 | BandMaths 12 | 13 | 14 | 15 | 16 | 17 | 18 | amp 19 | float32 20 | 20*log10(abs(QBAND+IBAND)) 21 | 22 | 23 | 0.0 24 | 25 | 26 | 27 | 28 | 29 | 30 | Multilook 31 | 32 | 33 | 34 | 35 | amp 36 | 20 37 | 5 38 | false 39 | true 40 | 41 | 42 | 43 | Write 44 | 45 | 46 | 47 | 48 | OUTPUTFOLDER/OUTPUTNAME.dim 49 | BEAM-DIMAP 50 | 51 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /graphs/stripmap_plot_coreg.xml: -------------------------------------------------------------------------------- 1 | 2 | 1.0 3 | 4 | Read 5 | 6 | 7 | INPUTFILE 8 | 9 | 10 | 11 | BandMaths 12 | 13 | 14 | 15 | 16 | 17 | 18 | amp 19 | float32 20 | 20*log10(abs(QBAND+IBAND)) 21 | 22 | 23 | 0.0 24 | 25 | 26 | 27 | 28 | 29 | 30 | Multilook 31 | 32 | 33 | 34 | 35 | amp 36 | 3 37 | 1 38 | false 39 | true 40 | 41 | 42 | 43 | Write 44 | 45 | 46 | 47 | 48 | OUTPUTFOLDER/OUTPUTNAME.dim 49 | BEAM-DIMAP 50 | 51 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /graphs/stripmap_plot_split.xml: -------------------------------------------------------------------------------- 1 | 2 | 1.0 3 | 4 | Read 5 | 6 | 7 | INPUTFILE 8 | 9 | 10 | 11 | BandMaths 12 | 13 | 14 | 15 | 16 | 17 | 18 | amp 19 | float32 20 | 20*log10(abs(QBAND+IBAND)) 21 | 22 | 23 | 0.0 24 | 25 | 26 | 27 | 28 | 29 | 30 | Multilook 31 | 32 | 33 | 34 | 35 | amp 36 | 3 37 | 1 38 | false 39 | true 40 | 41 | 42 | 43 | Write 44 | 45 | 46 | 47 | 48 | OUTPUTFOLDER/OUTPUTNAME.dim 49 | BEAM-DIMAP 50 | 51 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /snap2stamps_environment.yml: -------------------------------------------------------------------------------- 1 | name: snap2stamps 2 | channels: 3 | - r 4 | - defaults 5 | - eumetsat 6 | - https://conda.anaconda.org/conda-forge 7 | - conda-forge 8 | - mdelgadoblasco 9 | dependencies: 10 | - _libgcc_mutex=0.1 11 | - _openmp_mutex=5.1 12 | - blas=1.0 13 | - bzip2=1.0.8 14 | - ca-certificates=2023.05.30 15 | - geos=3.8.0 16 | - intel-openmp=2023.1.0 17 | - ld_impl_linux-64=2.38 18 | - libffi=3.4.4 19 | - libgcc-ng=11.2.0 20 | - libgomp=11.2.0 21 | - libstdcxx-ng=11.2.0 22 | - libuuid=1.41.5 23 | - mkl=2023.1.0 24 | - mkl-service=2.4.0 25 | - mkl_fft=1.3.6 26 | - mkl_random=1.2.2 27 | - ncurses=6.4 28 | - numpy=1.25.0 29 | - numpy-base=1.25.0 30 | - openssl=3.0.9 31 | - pip=23.1.2 32 | - python=3.11.3 33 | - readline=8.2 34 | - setuptools=67.8.0 35 | - shapely=2.0.1 36 | - s1tbx=9.0.2 37 | - sqlite=3.41.2 38 | - tbb=2021.8.0 39 | - tk=8.6.12 40 | - wheel=0.38.4 41 | - xz=5.4.2 42 | - zlib=1.2.13 43 | - pip: 44 | - argparse==1.4.0 45 | - asf-search==6.5.0 46 | - attrs==23.1.0 47 | - certifi==2023.5.7 48 | - charset-normalizer==3.1.0 49 | - cligj==0.7.2 50 | - configparser==5.3.0 51 | - dateparser==1.1.8 52 | - fiona==1.9.4.post1 53 | - geopandas==0.13.2 54 | - idna==3.4 55 | - importlib-metadata==6.7.0 56 | - packaging==23.1 57 | - pandas==2.0.2 58 | - pyproj==3.6.0 59 | - python-dateutil==2.8.2 60 | - pytz==2023.3 61 | - regex==2023.6.3 62 | - remotezip==0.12.1 63 | - requests==2.31.0 64 | - six==1.16.0 65 | - tabulate==0.9.0 66 | - tenacity==8.2.2 67 | - tzdata==2023.3 68 | - tzlocal==5.0.1 69 | - urllib3==2.0.3 70 | - zipp==3.15.0 71 | -------------------------------------------------------------------------------- /graphs/stripmap_DEM_Assisted_Coregistration.xml: -------------------------------------------------------------------------------- 1 | 2 | 1.0 3 | 4 | DEM-Assisted-Coregistration 5 | 6 | 7 | 8 | 9 | SRTM 1Sec HGT 10 | BILINEAR_INTERPOLATION 11 | 12 | 0.0 13 | BILINEAR_INTERPOLATION 14 | 100 15 | true 16 | false 17 | 18 | 19 | 20 | Write 21 | 22 | 23 | 24 | 25 | OUTPUTCOREGFOLDER/OUTPUTFILE 26 | BEAM-DIMAP 27 | 28 | 29 | 30 | ProductSet-Reader 31 | 32 | 33 | MASTER,SECONDARY 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /graphs/stripmap_DEM_Assisted_Coregistration_extDEM.xml: -------------------------------------------------------------------------------- 1 | 2 | 1.0 3 | 4 | DEM-Assisted-Coregistration 5 | 6 | 7 | 8 | 9 | External DEM 10 | BILINEAR_INTERPOLATION 11 | EXTERNALDEM 12 | 0.0 13 | BILINEAR_INTERPOLATION 14 | 100 15 | true 16 | false 17 | 18 | 19 | 20 | Write 21 | 22 | 23 | 24 | 25 | OUTPUTCOREGFOLDER/OUTPUTFILE 26 | BEAM-DIMAP 27 | 28 | 29 | 30 | ProductSet-Reader 31 | 32 | 33 | MASTER,SECONDARY 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /bin/project_topsar.conf: -------------------------------------------------------------------------------- 1 | #################### TOPSAR CONFIGURATION FILE ###################### 2 | ##################################################################### 3 | [PROJECT_DEFINITION] 4 | PROJECTFOLDER = D:/project 5 | GRAPHSFOLDER = D:/project/graphs 6 | ##################################################################### 7 | [PROC_OPTIONS] 8 | # Y / N OPTIONS 9 | OVERWRITE = N 10 | SMARTHDD = N 11 | PLOTTING = Y 12 | ##################################################################### 13 | [PROC_PARAMETERS] 14 | # SENSOR : S1 15 | SENSOR = S1 16 | POLARISATION = VV 17 | MASTER = D:/project/master/20220124.dim #example master 18 | # MASTER SEL : AUTO / FIRST / LAST / MANUAL 19 | MASTERSEL = AUTO 20 | EXTDEM = C:/Users/Desktop/DGM/external_dgm.tif 21 | ##################################################################### 22 | [AOI_DEFINITION] 23 | #AOI_MODE OPTIONS WKT / BBOX / SHP / KML / GeoJSON 24 | AOI_MODE = BBOX 25 | LONMIN = 7.43 26 | LATMIN = 51.20 27 | LONMAX = 7.57 28 | LATMAX = 51.28 29 | WKT = POLYGON((11.997 41.455,11.997 42.294,12.936 42.294,12.936 41.455,11.997 41.455)) 30 | AOI_FILE = /tmp/my_aoi.shp 31 | ##################################################################### 32 | [SEARCH_PARAMS] 33 | # autoDownload : Y / N 34 | autoDownload = N 35 | TRACK = 95 36 | # beamMode : SLC / GRD 37 | beamMode = SLC 38 | # START/ STOP in YYYY-MM-DD 39 | START = 2022-01-01 40 | END = 2022-04-16 41 | # SAT : S1 / S1A / S1B 42 | SAT= S1A 43 | ASF_USER = 44 | ASF_PASS = 45 | # Number of Parallel Downloads (NPD) 46 | [SEARCH_PDOWNLOADS] 47 | NPD = 4 48 | ##################################################################### 49 | [SNAP_GPT] 50 | SNAP_INSTALLATION_FOLDER = C:/Program Files/snap 51 | SNAP_HOME_DIR = C:/Program Files/.snap 52 | ##################################################################### 53 | [COMPUTING_RESOURCES] 54 | CPU = 14 55 | CACHE = 118G 56 | ##################################################################### 57 | -------------------------------------------------------------------------------- /graphs/topsar_master_split_applyorbit.xml: -------------------------------------------------------------------------------- 1 | 2 | 1.0 3 | 4 | Read 5 | 6 | 7 | INPUTFILE 8 | 9 | 10 | 11 | TOPSAR-Split 12 | 13 | 14 | 15 | 16 | IWs 17 | POLARISATION 18 | 1 19 | 10 20 | POLYGON 21 | 22 | 23 | 24 | Apply-Orbit-File 25 | 26 | 27 | 28 | 29 | Sentinel Precise (Auto Download) 30 | 3 31 | false 32 | 33 | 34 | 35 | Write 36 | 37 | 38 | 39 | 40 | OUTPUTFILE 41 | BEAM-DIMAP 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | -------------------------------------------------------------------------------- /graphs/topsar_secondaries_split_applyorbit.xml: -------------------------------------------------------------------------------- 1 | 2 | 1.0 3 | 4 | Read 5 | 6 | 7 | INPUTFILE 8 | 9 | 10 | 11 | TOPSAR-Split 12 | 13 | 14 | 15 | 16 | IWs 17 | POLARISATION 18 | 1 19 | 999 20 | POLYGON 21 | 22 | 23 | 24 | Apply-Orbit-File 25 | 26 | 27 | 28 | 29 | Sentinel Precise (Auto Download) 30 | 3 31 | false 32 | 33 | 34 | 35 | Write 36 | 37 | 38 | 39 | 40 | OUTPUTFILE 41 | BEAM-DIMAP 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | -------------------------------------------------------------------------------- /graphs/plot_phase.xml: -------------------------------------------------------------------------------- 1 | 2 | 1.0 3 | 4 | Read 5 | 6 | 7 | INPUTFILE 8 | 9 | 10 | 11 | BandMaths 12 | 13 | 14 | 15 | 16 | 17 | 18 | phase 19 | float32 20 | phase(QBAND,IBAND) 21 | 22 | 23 | 0.0 24 | 25 | 26 | 27 | 28 | 29 | 30 | Multilook 31 | 32 | 33 | 34 | 35 | 36 | 20 37 | 5 38 | false 39 | true 40 | 41 | 42 | 43 | Subset 44 | 45 | 46 | 47 | 48 | phase 49 | 0,0,24608,2844 50 | 51 | 1 52 | 1 53 | false 54 | 55 | true 56 | 57 | 58 | 59 | Write 60 | 61 | 62 | 63 | 64 | OUTPUTFOLDER/OUTPUTNAME.dim 65 | BEAM-DIMAP 66 | 67 | 68 | 69 | 70 | -------------------------------------------------------------------------------- /bin/topsar_step_0_secondaries_prep.py: -------------------------------------------------------------------------------- 1 | import os 2 | import sys 3 | import glob 4 | import configparser 5 | import argparse 6 | import warnings 7 | import shutil 8 | 9 | warnings.filterwarnings('ignore') 10 | 11 | 12 | parser = argparse.ArgumentParser(description='This script sorts the secondary Sentinel-1 images into folders') 13 | parser.add_argument("--ProjFile","-F", type=str) 14 | 15 | args = parser.parse_args() 16 | if not args.ProjFile: 17 | print("No Input File detected") 18 | sys.exit(-1) 19 | else: 20 | configfile = args.ProjFile 21 | 22 | 23 | print(configfile) 24 | 25 | config = configparser.ConfigParser() 26 | config.read(configfile) 27 | 28 | #print(config.sections()) 29 | #project=config['PROJECT_DEFINITION'] 30 | #for key in project: 31 | # print(key) 32 | 33 | PROJECTFOLDER=config['PROJECT_DEFINITION'].get('PROJECTFOLDER') 34 | 35 | #printing variables 36 | print(PROJECTFOLDER) 37 | 38 | 39 | directory=os.path.join(PROJECTFOLDER,'secondaries') 40 | 41 | safeFiles=len(sorted(glob.glob(directory+'/*SAFE/manifest.safe'))) 42 | print('Found '+str(safeFiles)+' Sentinel-1 uncompressed files') 43 | for filename in sorted(glob.glob(directory+'/*SAFE/manifest.safe')): 44 | if filename.startswith('S1'): 45 | name=os.path.join(directory,filename) 46 | print(name) 47 | head, tail = os.path.split(name) 48 | subdirectory=os.path.join(directory,tail[17:25]) 49 | if not os.path.exists(subdirectory): 50 | os.makedirs(subdirectory) 51 | source=name 52 | destination=os.path.join(subdirectory,tail) 53 | print('Moving '+source+' to '+destination) 54 | shutil.move(source,destination) 55 | else: 56 | continue 57 | 58 | safeFiles=len(sorted(glob.glob(directory+'/*zip'))) 59 | print('Found '+str(safeFiles)+' Sentinel-1 compressed files') 60 | for filename in sorted(glob.glob(directory+'/*.zip')): 61 | print(filename) 62 | if os.path.basename(filename).startswith('S1'): 63 | print(os.path.basename(filename)) 64 | subdirectory=os.path.join(directory,os.path.basename(filename)[17:25]) 65 | if not os.path.exists(subdirectory): 66 | os.makedirs(subdirectory) 67 | destination=os.path.join(subdirectory,os.path.basename(filename)) 68 | print('Moving '+filename+' to '+destination) 69 | shutil.move(filename,destination) 70 | else: 71 | continue 72 | 73 | 74 | -------------------------------------------------------------------------------- /graphs/topsar_plot_amplitude_deburst.xml: -------------------------------------------------------------------------------- 1 | 2 | 1.0 3 | 4 | Read 5 | 6 | 7 | INPUTFILE 8 | 9 | 10 | 11 | TOPSAR-Deburst 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | BandMaths 21 | 22 | 23 | 24 | 25 | 26 | 27 | amp 28 | float32 29 | 20*log10(abs(QBAND+IBAND)) 30 | 31 | 32 | 0.0 33 | 34 | 35 | 36 | 37 | 38 | 39 | Multilook 40 | 41 | 42 | 43 | 44 | amp 45 | 20 46 | 5 47 | false 48 | false 49 | 50 | 51 | 52 | Write 53 | 54 | 55 | 56 | 57 | OUTPUTFOLDER/OUTPUTNAME.dim 58 | BEAM-DIMAP 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | -------------------------------------------------------------------------------- /graphs/stripmap_Interferogram_TopoPhase_extDEM.xml: -------------------------------------------------------------------------------- 1 | 2 | 1.0 3 | 4 | Read 5 | 6 | 7 | COREGFILE 8 | 9 | 10 | 11 | Interferogram 12 | 13 | 14 | 15 | 16 | true 17 | 5 18 | 501 19 | 3 20 | false 21 | 8 22 | 10 23 | true 24 | false 25 | SRTM 3Sec 26 | 27 | 0.0 28 | true 29 | 100 30 | false 31 | false 32 | 33 | 34 | 35 | TopoPhaseRemoval 36 | 37 | 38 | 39 | 40 | 3 41 | External DEM 42 | EXTERNALDEM 43 | 0.0 44 | 100 45 | true 46 | true 47 | true 48 | 49 | 50 | 51 | Write 52 | 53 | 54 | 55 | 56 | OUTPUTIFGFOLDER/OUTPUTFILE 57 | BEAM-DIMAP 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | -------------------------------------------------------------------------------- /graphs/topsar_master_assemble_split_applyorbit.xml: -------------------------------------------------------------------------------- 1 | 2 | 1.0 3 | 4 | Read 5 | 6 | 7 | INPUTFILE1 8 | 9 | 10 | 11 | Read 12 | 13 | 14 | INPUTFILE2 15 | 16 | 17 | 18 | TOPSAR-Split 19 | 20 | 21 | 22 | 23 | IWs 24 | POLARISATION 25 | 1 26 | 999 27 | POLYGON 28 | 29 | 30 | 31 | SliceAssembly 32 | 33 | 34 | 35 | 36 | 37 | POLARISATION 38 | 39 | 40 | 41 | Apply-Orbit-File 42 | 43 | 44 | 45 | 46 | Sentinel Precise (Auto Download) 47 | 3 48 | false 49 | 50 | 51 | 52 | Write 53 | 54 | 55 | 56 | 57 | OUTPUTFILE 58 | BEAM-DIMAP 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | -------------------------------------------------------------------------------- /graphs/topsar_secondaries_assemble_split_applyorbit.xml: -------------------------------------------------------------------------------- 1 | 2 | 1.0 3 | 4 | Read 5 | 6 | 7 | INPUTFILE1 8 | 9 | 10 | 11 | Read 12 | 13 | 14 | INPUTFILE2 15 | 16 | 17 | 18 | TOPSAR-Split 19 | 20 | 21 | 22 | 23 | IWs 24 | POLARISATION 25 | 1 26 | 999 27 | POLYGON 28 | 29 | 30 | 31 | SliceAssembly 32 | 33 | 34 | 35 | 36 | 37 | POLARISATION 38 | 39 | 40 | 41 | Apply-Orbit-File 42 | 43 | 44 | 45 | 46 | Sentinel Precise (Auto Download) 47 | 3 48 | false 49 | 50 | 51 | 52 | Write 53 | 54 | 55 | 56 | 57 | OUTPUTFILE 58 | BEAM-DIMAP 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | -------------------------------------------------------------------------------- /graphs/stripmap_Interferogram_TopoPhase.xml: -------------------------------------------------------------------------------- 1 | 2 | 1.0 3 | 4 | Read 5 | 6 | 7 | false 8 | COREGFILE 9 | true 10 | 11 | 0,0,2147483647,2147483647 12 | 13 | 14 | 15 | 16 | Interferogram 17 | 18 | 19 | 20 | 21 | true 22 | 5 23 | 501 24 | 3 25 | false 26 | 8 27 | 10 28 | true 29 | false 30 | SRTM 3Sec 31 | 32 | 0.0 33 | true 34 | 100 35 | false 36 | false 37 | 38 | 39 | 40 | TopoPhaseRemoval 41 | 42 | 43 | 44 | 45 | 3 46 | SRTM 1Sec HGT 47 | 48 | 0.0 49 | 100 50 | true 51 | true 52 | true 53 | 54 | 55 | 56 | Write 57 | 58 | 59 | 60 | 61 | OUTPUTIFGFOLDER/OUTPUTFILE 62 | BEAM-DIMAP 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | -------------------------------------------------------------------------------- /bin/stripmap_step_1b_masterselection.py: -------------------------------------------------------------------------------- 1 | ### Python script to use SNAP as InSAR processor for TSX/TDX processing compatible with StaMPS PSI processing 2 | # Author: Jonas Ziemer, adapted from Jose Manuel Delgado Blasco (snap2stamps package) 3 | # Date: 01/01/2023 4 | # Version: 2.1, Python 3.9 5 | 6 | # Step 1: unzip downloaded TSX scenes (.tar; .tar.gz) 7 | # Step 2: preparing secondaries in folder structure 8 | # Step 3: subset TSX scenes 9 | # Step 4: Coregistration 10 | # Step 5: Interferogram generation 11 | # Step 6: StaMPS export 12 | 13 | 14 | import os 15 | import shutil 16 | import sys 17 | import glob 18 | import subprocess 19 | import shlex 20 | import time 21 | import configparser 22 | import argparse 23 | import warnings 24 | 25 | warnings.filterwarnings('ignore') 26 | 27 | parser = argparse.ArgumentParser(description='This script sorts the secondary SAR SLC images into folders') 28 | parser.add_argument("--ProjFile","-F", type=str) 29 | 30 | args = parser.parse_args() 31 | if not args.ProjFile: 32 | print("No Input File detected") 33 | sys.exit(-1) 34 | else: 35 | configfile = args.ProjFile 36 | 37 | 38 | print(configfile) 39 | 40 | 41 | config = configparser.ConfigParser() 42 | config.read(configfile) 43 | PROJECTFOLDER=config['PROJECT_DEFINITION'].get('PROJECTFOLDER') 44 | projectfolder=PROJECTFOLDER 45 | print(PROJECTFOLDER) 46 | 47 | bar_message='\n#####################################################################\n' 48 | 49 | 50 | ############################################################################## 51 | ######################## Slaves sortering in folders ######################### 52 | ############################################################################## 53 | # Folders involved in this processing step 54 | logfolder=os.path.join(PROJECTFOLDER,'logs') 55 | subsetfolder=os.path.join(PROJECTFOLDER,'subset') 56 | 57 | if not os.path.exists(logfolder): 58 | os.makedirs(logfolder) 59 | 60 | errorlog=os.path.join(logfolder,'masterselect_proc_stderr.log') 61 | outlog=os.path.join(logfolder,'masterselect_proc_stdout.log') 62 | out_file = open(outlog, 'a') 63 | err_file = open(errorlog, 'a') 64 | 65 | timeStarted_global = time.time() 66 | masterfolder=projectfolder + '/master' 67 | if not os.path.exists(masterfolder): 68 | os.makedirs(masterfolder) 69 | # Select master 70 | date = input("Enter the date of the masterscene in the format 'yyyymmdd' (Dont forget to specify the selected master file (yyyymmdd_sub.dim) in the project_stripmap.conf file (line 17)!):") 71 | # Forward the input to the autorun script 72 | sys.stdout.write(date) 73 | items = [] 74 | # Get a list of all items in the directory 75 | items = os.listdir(subsetfolder) 76 | 77 | # Find the items containing the selected date and move them to the "master" folder 78 | for item in items: 79 | if date in item: 80 | item_path = os.path.join(subsetfolder, item) 81 | shutil.move(item_path, masterfolder) 82 | print(f"Moved '{item}' to 'master' folder.") 83 | timeDelta_global = time.time() - timeStarted_global 84 | print('Finished preparation in ' + str(timeDelta_global) + ' seconds.\n') 85 | -------------------------------------------------------------------------------- /bin/stripmap_step_0b_secondaries_prep.py: -------------------------------------------------------------------------------- 1 | ### Python script to use SNAP as InSAR processor for TSX/TDX processing compatible with StaMPS PSI processing 2 | # Author: Jonas Ziemer, adapted from Jose Manuel Delgado Blasco (snap2stamps package) 3 | # Date: 01/01/2023 4 | # Version: 2.1, Python 3.9 5 | 6 | # Step 1: unzip downloaded TSX scenes (.tar; .tar.gz) 7 | # Step 2: preparing secondaries in folder structure 8 | # Step 3: subset TSX scenes 9 | # Step 4: Coregistration 10 | # Step 5: Interferogram generation 11 | # Step 6: StaMPS export 12 | 13 | 14 | import os 15 | import shutil 16 | import sys 17 | import glob 18 | import subprocess 19 | import shlex 20 | import time 21 | import configparser 22 | import argparse 23 | import warnings 24 | 25 | warnings.filterwarnings('ignore') 26 | 27 | parser = argparse.ArgumentParser(description='This script sorts the secondary SAR SLC images into folders') 28 | parser.add_argument("--ProjFile","-F", type=str) 29 | 30 | args = parser.parse_args() 31 | if not args.ProjFile: 32 | print("No Input File detected") 33 | sys.exit(-1) 34 | else: 35 | configfile = args.ProjFile 36 | 37 | 38 | print(configfile) 39 | 40 | 41 | config = configparser.ConfigParser() 42 | config.read(configfile) 43 | PROJECTFOLDER=config['PROJECT_DEFINITION'].get('PROJECTFOLDER') 44 | print(PROJECTFOLDER) 45 | 46 | bar_message='\n#####################################################################\n' 47 | 48 | 49 | ############################################################################## 50 | ######################## Slaves sortering in folders ######################### 51 | ############################################################################## 52 | # Folders involved in this processing step 53 | logfolder=os.path.join(PROJECTFOLDER,'logs') 54 | secondariesfolder=os.path.join(PROJECTFOLDER,'secondaries') 55 | 56 | if not os.path.exists(logfolder): 57 | os.makedirs(logfolder) 58 | 59 | errorlog=os.path.join(logfolder,'secondaries_proc_stderr.log') 60 | outlog=os.path.join(logfolder,'secondaries_proc_stdout.log') 61 | out_file = open(outlog, 'a') 62 | err_file = open(errorlog, 'a') 63 | 64 | timeStarted_global = time.time() 65 | # Iterate trough all files in the secondariesfolder 66 | for filename in os.listdir(secondariesfolder): 67 | if filename.startswith("TDX1_SAR__SSC______SM_S_SRA") or filename.startswith("TSX1_SAR__SSC______SM_S_SRA"): 68 | print(os.path.join(secondariesfolder, filename)) 69 | # Create name of the output secondaries folder 70 | head, tail = os.path.split(os.path.join(secondariesfolder, filename)) 71 | print(tail[28:36]) 72 | subdirectory=secondariesfolder + '/' + tail[28:36] 73 | if not os.path.exists(subdirectory): 74 | os.makedirs(subdirectory) 75 | # Create subdirectories 76 | source=os.path.join(secondariesfolder, filename) 77 | destination=os.path.join(subdirectory, tail) 78 | print('Moving '+source+' to '+ destination) 79 | shutil.move(source,destination) 80 | else: 81 | continue 82 | timeDelta_global = time.time() - timeStarted_global 83 | print('Finished preparation in ' + str(timeDelta_global) + ' seconds.\n') 84 | -------------------------------------------------------------------------------- /graphs/topsar_export_mergeIW_subset.xml: -------------------------------------------------------------------------------- 1 | 2 | 1.0 3 | 4 | TOPSAR-Merge 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | TOPSAR-Merge 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | TopoPhaseRemoval 23 | 24 | 25 | 26 | 27 | 3 28 | SRTM 1Sec HGT 29 | 30 | 0.0 31 | 100 32 | true 33 | true 34 | true 35 | 36 | 37 | 38 | Subset 39 | 40 | 41 | 42 | 43 | 44 | 0,0,0,0 45 | POLYGON 46 | 1 47 | 1 48 | false 49 | 50 | true 51 | 52 | 53 | 54 | Subset 55 | 56 | 57 | 58 | 59 | 60 | 0,0,0,0 61 | POLYGON 62 | 1 63 | 1 64 | false 65 | 66 | true 67 | 68 | 69 | 70 | ProductSet-Reader 71 | 72 | 73 | IFGFILE 74 | 75 | 76 | 77 | ProductSet-Reader 78 | 79 | 80 | COREGFILE 81 | 82 | 83 | 84 | StampsExport 85 | 86 | 87 | 88 | 89 | 90 | OUTPUTFOLDER 91 | true 92 | 93 | 94 | 95 | -------------------------------------------------------------------------------- /graphs/topsar_export_mergeIW_subset_extDEM.xml: -------------------------------------------------------------------------------- 1 | 2 | 1.0 3 | 4 | TOPSAR-Merge 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | TOPSAR-Merge 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | TopoPhaseRemoval 23 | 24 | 25 | 26 | 27 | 3 28 | External DEM 29 | EXTERNALDEM 30 | 0.0 31 | 100 32 | true 33 | true 34 | true 35 | 36 | 37 | 38 | Subset 39 | 40 | 41 | 42 | 43 | 44 | 0,0,0,0 45 | POLYGON 46 | 1 47 | 1 48 | false 49 | 50 | true 51 | 52 | 53 | 54 | Subset 55 | 56 | 57 | 58 | 59 | 60 | 0,0,0,0 61 | POLYGON 62 | 1 63 | 1 64 | false 65 | 66 | true 67 | 68 | 69 | 70 | ProductSet-Reader 71 | 72 | 73 | IFGFILE 74 | 75 | 76 | 77 | ProductSet-Reader 78 | 79 | 80 | COREGFILE 81 | 82 | 83 | 84 | StampsExport 85 | 86 | 87 | 88 | 89 | 90 | OUTPUTFOLDER 91 | true 92 | 93 | 94 | 95 | -------------------------------------------------------------------------------- /bin/topsar_automaster.py: -------------------------------------------------------------------------------- 1 | import os 2 | import sys 3 | import numpy as np 4 | import configparser 5 | import argparse 6 | import warnings 7 | 8 | warnings.filterwarnings('ignore') 9 | 10 | parser = argparse.ArgumentParser(description='This script selects a Master image if AUTO mode was selected') 11 | parser.add_argument("--ProjFile","-F", type=str) 12 | parser.add_argument("--Mode","-M", type=str) 13 | 14 | args = parser.parse_args() 15 | 16 | def usage(): 17 | message='####################################################\n' 18 | message=message+'Usage: python '+sys.argv[0]+' -F [project.conf] -M [mode] \n' 19 | message=message+' project.conf file\n' 20 | message=message+' mode : AUTO/FIRST/LAST\n' 21 | message=message+'All parameters mandatory' 22 | return message 23 | 24 | if not args.ProjFile: 25 | print("No Input File detected") 26 | print(usage()) 27 | sys.exit(-1) 28 | else: 29 | configfile = args.ProjFile 30 | if not args.Mode: 31 | print('No Mode selected') 32 | print(usage()) 33 | sys.exit(-1) 34 | else: 35 | mode=args.Mode 36 | 37 | 38 | print(configfile) 39 | config = configparser.ConfigParser() 40 | config.read(configfile) 41 | 42 | PROJECTFOLDER=config['PROJECT_DEFINITION'].get('PROJECTFOLDER') 43 | MASTERFOLDER=config['PROC_PARAMETERS'].get('MASTER') 44 | MODE=config['PROC_PARAMETERS'].get('MASTERSEL') 45 | 46 | #printing variables 47 | print(PROJECTFOLDER) 48 | secondaries=os.path.join(PROJECTFOLDER,'secondaries') 49 | 50 | ## Searching secondaries folders and files downloaded 51 | print(len(next(os.walk(secondaries))[1])) 52 | 53 | files = folders = 0 54 | for _, dirnames, filenames in os.walk(secondaries): 55 | # ^ this idiom means "we won't be using this value" 56 | files += len(filenames) 57 | folders += len(dirnames) 58 | print ("{:,} files, {:,} folders".format(files, folders)) 59 | 60 | dirs=next(os.walk(secondaries))[1] 61 | print(dirs) 62 | 63 | options=range(folders+1) 64 | print(options) 65 | 66 | import numpy as np 67 | if mode=='AUTO': 68 | sel=int(np.floor(folders/2)-1) 69 | print(sel) 70 | elif int(mode) in options: 71 | sel=int(mode)-1 72 | print(sel) 73 | elif mode=='FIRST': 74 | sel=options[0] 75 | elif mode=='LAST': 76 | sel=options[-1] 77 | elif mode=='MANUAL': 78 | print("Master selection defined MANUAL. Please proceed accordingly!") 79 | sys.exit() 80 | else: 81 | print('No valid option found! Using automaster!') 82 | sel=int(np.floor(folders/2)-1) 83 | print('Selected Master date: '+dirs[sel]) 84 | 85 | try: 86 | if sel is not None: 87 | ## Moving files to MASTER folder 88 | source = os.path.join(secondaries,dirs[sel]) 89 | destination = MASTERFOLDER 90 | print(destination) 91 | # gather all files 92 | allfiles = os.listdir(source) 93 | print(allfiles) 94 | 95 | # iterate on all files to move them to destination folder 96 | for f in allfiles: 97 | src_path = os.path.join(source, f) 98 | dst_path = os.path.join(destination, f) 99 | os.rename(src_path, dst_path) 100 | 101 | # Remove empty folder from secondaries folder 102 | os.rmdir(os.path.join(secondaries,dirs[sel])) 103 | except: 104 | print('Master to be selected and prepared manually by the user') 105 | pass 106 | 107 | -------------------------------------------------------------------------------- /bin/stripmap_step_0a_unpack_sar_scenes.py: -------------------------------------------------------------------------------- 1 | ### Python script to use SNAP as InSAR processor for TSX/TDX processing compatible with StaMPS PSI processing 2 | # Author: Jonas Ziemer, adapted from Jose Manuel Delgado Blasco (snap2stamps package) 3 | # Date: 01/01/2023 4 | # Version: 2.1, Python 3.9 5 | 6 | # Step 1: unzip downloaded TSX scenes (.tar; .tar.gz) 7 | # Step 2: preparing secondaries in folder structure 8 | # Step 3: subset TSX scenes 9 | # Step 4: Coregistration 10 | # Step 5: Interferogram generation 11 | # Step 6: StaMPS export 12 | 13 | 14 | import os 15 | import shutil 16 | import sys 17 | import glob 18 | import subprocess 19 | import shlex 20 | import time 21 | import tarfile 22 | 23 | import configparser 24 | import argparse 25 | import warnings 26 | 27 | warnings.filterwarnings('ignore') 28 | 29 | parser = argparse.ArgumentParser(description='This script unpacks the original TSX/TDX data') 30 | parser.add_argument("--ProjFile","-F", type=str) 31 | 32 | args = parser.parse_args() 33 | if not args.ProjFile: 34 | print("No Input File detected") 35 | sys.exit(-1) 36 | else: 37 | configfile = args.ProjFile 38 | 39 | 40 | print(configfile) 41 | 42 | 43 | config = configparser.ConfigParser() 44 | config.read(configfile) 45 | PROJECTFOLDER=config['PROJECT_DEFINITION'].get('PROJECTFOLDER') 46 | print(PROJECTFOLDER) 47 | 48 | bar_message='\n#####################################################################\n' 49 | 50 | ############################################################################## 51 | ################### Unpack zipped files in the zipfolder ##################### 52 | ############################################################################## 53 | # Folders involved in this processing step 54 | logfolder=os.path.join(PROJECTFOLDER,'logs') 55 | zipfolder=os.path.join(PROJECTFOLDER,'zipfiles') 56 | secondariesfolder=os.path.join(PROJECTFOLDER,'secondaries') 57 | 58 | if not os.path.exists(logfolder): 59 | os.makedirs(logfolder) 60 | if not os.path.exists(zipfolder): 61 | os.makedirs(zipfolder) 62 | if not os.path.exists(secondariesfolder): 63 | os.makedirs(secondariesfolder) 64 | 65 | errorlog=os.path.join(logfolder,'unpack_proc_stderr.log') 66 | outlog=os.path.join(logfolder,'unpack_proc_stdout.log') 67 | out_file = open(outlog, 'a') 68 | err_file = open(errorlog, 'a') 69 | 70 | timeStarted_global = time.time() 71 | # Unpack .tar(.gz) files 72 | try: 73 | for filename in os.listdir(zipfolder): 74 | os.chdir(zipfolder) 75 | filename = zipfolder + '/' + filename 76 | print(filename) 77 | if filename.endswith("tar.gz"): 78 | tar = tarfile.open(filename, "r:gz") 79 | if filename.endswith("tar"): 80 | tar = tarfile.open(filename, "r:") 81 | elif filename.endswith("tar"): 82 | tar = tarfile.open(filename, "r:") 83 | tar.extractall() 84 | tar.close() 85 | except: 86 | raise Exception("The files have already been extracted!") 87 | 88 | # Cut out the data folder only, to get the right naming of the files for later processing steps 89 | for file in os.listdir(zipfolder): 90 | folder = os.path.join(zipfolder, file) 91 | if os.path.isdir(folder): 92 | for tsxmainfolder in glob.iglob(folder + '/*'): 93 | if tsxmainfolder.endswith('.L1B'): 94 | for tsxsubfolder in glob.iglob(tsxmainfolder + '/*'): 95 | print(tsxsubfolder) 96 | shutil.move(tsxsubfolder, secondariesfolder) 97 | timeDelta_global = time.time() - timeStarted_global 98 | print('Finished unzipping in ' + str(timeDelta_global) + ' seconds.\n') 99 | -------------------------------------------------------------------------------- /bin/auto_run.py: -------------------------------------------------------------------------------- 1 | from subprocess import Popen, PIPE, STDOUT 2 | import os 3 | import sys 4 | import time 5 | import warnings 6 | import argparse 7 | import configparser 8 | import subprocess 9 | 10 | warnings.filterwarnings('ignore') 11 | sys.stdout.flush() 12 | 13 | parser = argparse.ArgumentParser(description='This script runs automatically all the steps for single master DInSAR processing') 14 | parser.add_argument("--ProjFile","-F", type=str) 15 | 16 | args = parser.parse_args() 17 | if not args.ProjFile: 18 | print("No Input File detected") 19 | sys.exit(-1) 20 | else: 21 | configfile = args.ProjFile 22 | 23 | #################################################### 24 | def execute(step,param1,param2): 25 | if 'step_4' in step or 'automaster' in step: 26 | args = [ 'python', step, '-F', param1, '-M', param2] 27 | else: 28 | args = [ 'python', step, '-F', param1] 29 | print( args) 30 | # Launching process 31 | timeStarted = time.time() 32 | process = Popen(args, bufsize=1, stdout=PIPE, stderr=STDOUT) 33 | r = b"" 34 | for line in process.stdout: 35 | r += line 36 | print(line.decode('utf-8')) 37 | process.wait() 38 | timeDelta = time.time() - timeStarted 39 | # Get execution time. 40 | print(' Finished process in '+str(timeDelta)+' seconds.') 41 | if process.returncode != 0 : 42 | message='Error running '+step+'\n' 43 | else: 44 | message='Step '+step+' successfully completed.\n' 45 | print(message) 46 | return process.returncode 47 | 48 | #config=sys.argv[1] 49 | # Getting configuration variables from inputfile 50 | config = configparser.ConfigParser() 51 | config.read(configfile) 52 | PLOTTING=config['PROC_OPTIONS'].get('PLOTTING') 53 | #DOWNLOAD=config['SEARCH_PARAMS'].get('autoDownload') 54 | SENSOR=config['PROC_PARAMETERS'].get('SENSOR') 55 | #MASTERSEL=config['PROC_PARAMETERS'].get('MASTERSEL') 56 | ## Execute the different steps 57 | if SENSOR == 'S1': 58 | DOWNLOAD=config['SEARCH_PARAMS'].get('autoDownload') 59 | MASTERSEL=config['PROC_PARAMETERS'].get('MASTERSEL') 60 | if DOWNLOAD == 'Y': 61 | execute('asf_s1_downloader.py', configfile,'') 62 | 63 | execute('topsar_step_0_secondaries_prep.py', configfile,'') 64 | if MASTERSEL!='MANUAL': 65 | execute('topsar_automaster.py', configfile, MASTERSEL) 66 | execute('topsar_step_1_splitting_master_multi_IW.py',configfile,'') 67 | execute('topsar_step_2_splitting_secondaries.py', configfile,'') 68 | execute('topsar_step_3_coreg_ifg_topsar_smart.py', configfile,'') 69 | 70 | if PLOTTING == 'Y': 71 | execute('topsar_step_4_plotting_all.py', configfile, 'ifg') 72 | execute('topsar_step_4_plotting_all.py', configfile,'coreg') 73 | 74 | execute('topsar_step_5_stamps_export_multiIW.py', configfile,'') 75 | 76 | elif SENSOR == 'TSX' or SENSOR == 'TDX': 77 | execute('stripmap_step_0a_unpack_sar_scenes.py', configfile,'') 78 | execute('stripmap_step_0b_secondaries_prep.py', configfile,'') 79 | execute('stripmap_step_1_subset_sar.py', configfile,'') 80 | subprocess.call(['python', 'stripmap_step_1b_masterselection.py'] + list(sys.argv[1:])) 81 | execute('stripmap_step_2_coreg_sar.py', configfile,'') 82 | execute('stripmap_step_3_ifg_sar.py', configfile,'') 83 | 84 | if PLOTTING == 'Y': 85 | execute('stripmap_step_4_plotting_all.py', configfile, 'split') 86 | execute('stripmap_step_4_plotting_all.py', configfile, 'ifg') 87 | execute('stripmap_step_4_plotting_all.py', configfile,'coreg') 88 | 89 | execute('stripmap_step_5_stamps_export.py', configfile, '') 90 | else: 91 | print('Sensor not recognized! Please check project configuration file') 92 | print('Processing terminated') 93 | print('In case sensor is not S1, TSX or TDX you may run the scripts under your own responsability as these scripts had not been tested yet with other sensors') 94 | print('Feedback welcome through the STEP Forum https://step.esa.int') 95 | 96 | -------------------------------------------------------------------------------- /bin/asf_s1_downloader.py: -------------------------------------------------------------------------------- 1 | import os 2 | import sys 3 | import configparser 4 | import argparse 5 | import asf_search as asf 6 | import warnings 7 | warnings.filterwarnings('ignore') 8 | 9 | parser=argparse.ArgumentParser(description='This script downloads Sentinel-1 data from Alaska Satellite Facilities') 10 | parser.add_argument("--ProjFile","-F",type=str) 11 | 12 | args=parser.parse_args() 13 | if not args.ProjFile: 14 | print("No Input File detected") 15 | sys.exit(-1) 16 | else: 17 | configfile=args.ProjFile 18 | 19 | print(configfile) 20 | config=configparser.ConfigParser() 21 | config.read(configfile) 22 | 23 | PROJECTFOLDER=config['PROJECT_DEFINITION'].get('PROJECTFOLDER') 24 | directory=os.path.join(PROJECTFOLDER,'secondaries') 25 | print(directory) 26 | 27 | TRACK=int(config['SEARCH_PARAMS'].get('TRACK')) 28 | beamMode=config['SEARCH_PARAMS'].get('beamMode') 29 | START=config['SEARCH_PARAMS'].get('START') 30 | END=config['SEARCH_PARAMS'].get('END') 31 | SAT=config['SEARCH_PARAMS'].get('SAT') 32 | 33 | print(TRACK) 34 | print(beamMode) 35 | print(START) 36 | print(END) 37 | 38 | USER=config['SEARCH_PARAMS'].get('ASF_USER') 39 | PASS=config['SEARCH_PARAMS'].get('ASF_PASS') 40 | NPD=int(config['SEARCH_PDOWNLOADS'].get('NPD')) 41 | 42 | if not os.path.exists(directory): 43 | os.makedirs(directory) 44 | 45 | 46 | if SAT == "S1": 47 | myplatform=asf.SENTINEL1 48 | elif SAT == "S1A": 49 | myplatform=asf.SENTINEL1A 50 | elif SAT =="S1B": 51 | myplatform=asf.SENTINEL1B 52 | print(myplatform) 53 | 54 | if beamMode=="SLC": 55 | procType=[asf.PRODUCT_TYPE.SLC] 56 | else: 57 | procType=[asf.PRODUCT_TYPE.GRD_HD,asf.PRODUCT_TYPE.GRD_HS] 58 | 59 | print(procType) 60 | 61 | ########################################################### 62 | ## INITITATING SESSION WITH CREDENTIALS 63 | session=asf.ASFSession() 64 | session.auth_with_creds(USER,PASS) 65 | 66 | ######################################################### 67 | ## GETTING AOI DEFINITION 68 | #print('###############################################') 69 | #print('Getting AOI') 70 | aoi_mode=config['AOI_DEFINITION'].get('AOI_MODE') 71 | print(aoi_mode) 72 | if aoi_mode == 'WKT': 73 | polygon=config['AOI_DEFINITION'].get('WKT') 74 | elif aoi_mode == 'BBOX': 75 | LONMIN=config['AOI_DEFINITION'].get('LONMIN') 76 | LATMIN=config['AOI_DEFINITION'].get('LATMIN') 77 | LONMAX=config['AOI_DEFINITION'].get('LONMAX') 78 | LATMAX=config['AOI_DEFINITION'].get('LATMAX') 79 | polygon='POLYGON (('+LONMIN+' '+LATMIN+','+LONMAX+' '+LATMIN+','+LONMAX+' '+LATMAX+','+LONMIN+' '+LATMAX+','+LONMIN+' '+LATMIN+'))' 80 | elif aoi_mode == 'SHP' or aoi_mode == 'GeoJSON' or aoi_mode == 'KML': 81 | AOIFile=config['AOI_DEFINITION'].get('AOI_FILE') 82 | import geopandas as gpd 83 | if aoi_mode != 'KML': 84 | gdf=gpd.read_file(AOIFile) 85 | else: 86 | import fiona 87 | fiona.drvsupport.supported_drivers['KML'] = 'rw' 88 | gdf = gpd.read_file(AOIFile, driver='KML') 89 | #polygon=str(gdf['geometry'].wkt) 90 | 91 | #from shapely import wkt 92 | # polygon = wkt.dumps(gdf['geometry'][0]) 93 | #polygon=gdf['geometry'].envelop 94 | # bounds=gdf.bounds 95 | bbox=str(gdf.envelope[0]) 96 | polygon=bbox 97 | # print(bbox) 98 | # print(polygon) 99 | else: 100 | print('Wrong AOI_MODE parameter! Please revise the configuration file') 101 | sys.exit() 102 | 103 | print( polygon) 104 | wkt=polygon 105 | print(wkt) 106 | ################################################################### 107 | # QUERYING ASF 108 | print('#########################################################') 109 | print('Quering ASF with the defined parameteres') 110 | results=asf.geo_search(platform=[myplatform],beamMode=[asf.IW],processingLevel=procType,relativeOrbit=TRACK,intersectsWith=wkt,start=START,end=END,maxResults=1000) 111 | print(len(results)) 112 | 113 | ################################################### 114 | # STARTING DOWNLOAD 115 | print('#######################################################') 116 | print('Starting download') 117 | results.download(path=directory,session=session,processes=NPD) 118 | 119 | -------------------------------------------------------------------------------- /graphs/topsar_coreg_ifg_computation_noESD.xml: -------------------------------------------------------------------------------- 1 | 2 | 1.0 3 | 4 | Read 5 | 6 | 7 | MASTER 8 | 9 | 10 | 11 | Read 12 | 13 | 14 | SECONDARY 15 | 16 | 17 | 18 | Back-Geocoding 19 | 20 | 21 | 22 | 23 | 24 | SRTM 1Sec HGT 25 | BILINEAR_INTERPOLATION 26 | 27 | 0.0 28 | BILINEAR_INTERPOLATION 29 | false 30 | false 31 | false 32 | false 33 | 34 | 35 | 36 | Interferogram 37 | 38 | 39 | 40 | 41 | true 42 | 5 43 | 501 44 | 3 45 | false 46 | 2 47 | 10 48 | true 49 | false 50 | SRTM 1Sec HGT 51 | 52 | 0.0 53 | 54 | 100 55 | true 56 | true 57 | 58 | 59 | 60 | TOPSAR-Deburst 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | TOPSAR-Deburst 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | Write 79 | 80 | 81 | 82 | 83 | OUTPUTCOREGFOLDER/OUTPUTFILE.dim 84 | BEAM-DIMAP 85 | 86 | 87 | 88 | Write 89 | 90 | 91 | 92 | 93 | OUTPUTIFGFOLDER/OUTPUTFILE.dim 94 | BEAM-DIMAP 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | -------------------------------------------------------------------------------- /graphs/topsar_coreg_ifg_computation_noESD_extDEM.xml: -------------------------------------------------------------------------------- 1 | 2 | 1.0 3 | 4 | Read 5 | 6 | 7 | MASTER 8 | 9 | 10 | 11 | Read 12 | 13 | 14 | SECONDARY 15 | 16 | 17 | 18 | Back-Geocoding 19 | 20 | 21 | 22 | 23 | 24 | External DEM 25 | BILINEAR_INTERPOLATION 26 | EXTERNALDEM 27 | 0.0 28 | BILINEAR_INTERPOLATION 29 | false 30 | false 31 | false 32 | false 33 | 34 | 35 | 36 | Interferogram 37 | 38 | 39 | 40 | 41 | true 42 | 5 43 | 501 44 | 3 45 | false 46 | 2 47 | 10 48 | true 49 | false 50 | SRTM 1Sec HGT 51 | 52 | 0.0 53 | 54 | 100 55 | true 56 | true 57 | 58 | 59 | 60 | TOPSAR-Deburst 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | TOPSAR-Deburst 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | Write 79 | 80 | 81 | 82 | 83 | OUTPUTCOREGFOLDER/OUTPUTFILE.dim 84 | BEAM-DIMAP 85 | 86 | 87 | 88 | Write 89 | 90 | 91 | 92 | 93 | OUTPUTIFGFOLDER/OUTPUTFILE.dim 94 | BEAM-DIMAP 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | -------------------------------------------------------------------------------- /bin/stripmap_step_5_stamps_export.py: -------------------------------------------------------------------------------- 1 | ### Python script to use SNAP as InSAR processor for TSX/TDX processing compatible with StaMPS PSI processing 2 | # Author: Jonas Ziemer, adapted from Jose Manuel Delgado Blasco (snap2stamps package) 3 | # Date: 01/01/2023 4 | # Version: 2.1, Python 3.9 5 | 6 | # Step 1: unzip downloaded TSX scenes (.tar; .tar.gz) 7 | # Step 2: preparing secondaries in folder structure 8 | # Step 3: subset TSX scenes 9 | # Step 4: Coregistration 10 | # Step 5: Interferogram generation 11 | # Step 6: StaMPS export 12 | 13 | 14 | import os 15 | from pathlib import Path 16 | import sys 17 | import glob 18 | import subprocess 19 | import shlex 20 | import time 21 | import warnings 22 | import argparse 23 | import configparser 24 | 25 | warnings.filterwarnings('ignore') 26 | sys.stdout.flush() 27 | 28 | parser = argparse.ArgumentParser(description='This script runs the TerraSAR-X Interferogram computation and TopoPhase removal') 29 | parser.add_argument("--ProjFile","-F", type=str) 30 | 31 | args = parser.parse_args() 32 | if not args.ProjFile: 33 | print("No Input File detected") 34 | sys.exit(-1) 35 | else: 36 | configfile = args.ProjFile 37 | 38 | bar_message='\n#####################################################################\n' 39 | 40 | os.environ["LD_LIBRARY_PATH"] ="." 41 | # Getting configuration variables from inputfile 42 | config = configparser.ConfigParser() 43 | config.read(configfile) 44 | 45 | PROJECT=config['PROJECT_DEFINITION'].get('PROJECTFOLDER') 46 | GRAPH=config['PROJECT_DEFINITION'].get('GRAPHSFOLDER') 47 | 48 | OVERWRITE=config['PROC_OPTIONS'].get('OVERWRITE') 49 | SMARTHDD=config['PROC_OPTIONS'].get('SMARTHDD') 50 | CACHE=config['COMPUTING_RESOURCES'].get('CACHE') 51 | CPU=config['COMPUTING_RESOURCES'].get('CPU') 52 | MASTERFOLDER=config['PROC_PARAMETERS'].get('MASTER') 53 | masterfolder=MASTERFOLDER 54 | 55 | ################################################################### 56 | ## GETTING PATH to gpt executable 57 | SNAPFOLDER=config['SNAP_GPT'].get('SNAP_INSTALLATION_FOLDER') 58 | GPT=os.path.join(SNAPFOLDER,'bin','gpt') 59 | if os.name == 'nt': 60 | GPT=os.path.join(SNAPFOLDER,'bin','gpt.exe') 61 | 62 | ############################################################################ 63 | # Checking GPT 64 | if not os.path.exists(GPT): 65 | errormessage="GPT executable not found in "+GPT+".Processing aborted" 66 | print(errormessage) 67 | sys.exit(errormessage) 68 | ################################################################################### 69 | ############################# StaMPS PSI export ################################### 70 | ################################################################################### 71 | # Folders involved in this processing step 72 | coregfolder=os.path.join(PROJECT,'coreg') 73 | ifgfolder=os.path.join(PROJECT,'ifg') 74 | head, tail = os.path.split(masterfolder) 75 | outputexportfolder=os.path.join(PROJECT,'INSAR_'+tail[0:8]) 76 | logfolder=os.path.join(PROJECT,'logs') 77 | 78 | if not os.path.exists(outputexportfolder): 79 | os.makedirs(outputexportfolder) 80 | if not os.path.exists(logfolder): 81 | os.makedirs(logfolder) 82 | 83 | outlog=os.path.join(logfolder,'export_proc_stdout.log') 84 | 85 | # Original Snap graph and replaced Snap graph for subsettting 86 | graphxml=os.path.join(GRAPH,'stripmap_Export.xml') 87 | print(graphxml) 88 | graph2run=os.path.join(GRAPH,'export2run.xml') 89 | 90 | out_file = open(outlog, 'a') 91 | err_file=out_file 92 | 93 | # Processing layout 94 | print(bar_message) 95 | out_file.write(bar_message) 96 | message='## StaMPS PSI export started:\n' 97 | print(message) 98 | out_file.write(message) 99 | print(bar_message) 100 | out_file.write(bar_message) 101 | k=0 102 | timeStarted_global = time.time() 103 | # Iterate trough all files in the coreg- and ifg folder 104 | for dimfile in glob.iglob(coregfolder + '/*.dim'): 105 | head, tail = os.path.split(os.path.join(coregfolder, dimfile)) 106 | k=k+1 107 | message='['+str(k)+'] Exporting pair: master-secondary pair '+tail+'\n' 108 | ifgdim = Path(ifgfolder+'/'+tail) 109 | print(ifgdim) 110 | if ifgdim.is_file(): 111 | print(message) 112 | out_file.write(message) 113 | with open(graphxml, 'r') as file: 114 | filedata = file.read() 115 | # Replace the target string and generate a new file with replaced names for use in SNAP 116 | filedata = filedata.replace('COREGFILE',dimfile) 117 | filedata = filedata.replace('IFGFILE',str(ifgdim)) 118 | filedata = filedata.replace('OUTPUTFOLDER',outputexportfolder) 119 | with open(graph2run, 'w') as file: 120 | file.write(filedata) 121 | args = [ GPT, graph2run, '-c', CACHE, '-q', CPU] 122 | print(args) 123 | # Launch the processing 124 | process = subprocess.Popen(args, stdout=subprocess.PIPE,stderr=subprocess.STDOUT) 125 | timeStarted = time.time() 126 | stdout = process.communicate()[0] 127 | print('SNAP STDOUT:{}'.format(stdout)) 128 | # Get execution time 129 | timeDelta = time.time() - timeStarted 130 | print('['+str(k)+'] Finished process in '+str(timeDelta)+' seconds.') 131 | out_file.write('['+str(k)+'] Finished process in '+str(timeDelta)+' seconds.\n') 132 | if process.returncode != 0 : 133 | message='Error exporting '+str(tail)+'\n' 134 | err_file.write(message) 135 | else: 136 | message='Stamps export of '+str(tail)+' successfully completed.\n' 137 | print(message) 138 | out_file.write(message) 139 | print(bar_message) 140 | out_file.write(bar_message) 141 | timeDelta_global = time.time() - timeStarted_global 142 | print('Finished Stamps export in ' + str(timeDelta_global) + ' seconds.\n') 143 | out_file.close() 144 | err_file.close() 145 | -------------------------------------------------------------------------------- /graphs/topsar_coreg_ifg_computation.xml: -------------------------------------------------------------------------------- 1 | 2 | 1.0 3 | 4 | Read 5 | 6 | 7 | MASTER 8 | 9 | 10 | 11 | Read 12 | 13 | 14 | SECONDARY 15 | 16 | 17 | 18 | Back-Geocoding 19 | 20 | 21 | 22 | 23 | 24 | SRTM 1Sec HGT 25 | BILINEAR_INTERPOLATION 26 | 27 | 0.0 28 | BILINEAR_INTERPOLATION 29 | false 30 | false 31 | false 32 | false 33 | 34 | 35 | 36 | Enhanced-Spectral-Diversity 37 | 38 | 39 | 40 | 41 | 512 42 | 512 43 | 16 44 | 16 45 | 128 46 | 0.1 47 | 0.15 48 | 10 49 | false 50 | 0.0 51 | false 52 | 0.0 53 | 54 | 55 | 56 | Interferogram 57 | 58 | 59 | 60 | 61 | true 62 | 5 63 | 501 64 | 3 65 | false 66 | 2 67 | 10 68 | true 69 | false 70 | SRTM 1Sec HGT 71 | 72 | 0.0 73 | 74 | 100 75 | true 76 | true 77 | 78 | 79 | 80 | TOPSAR-Deburst 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | TOPSAR-Deburst 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | Write 99 | 100 | 101 | 102 | 103 | OUTPUTCOREGFOLDER/OUTPUTFILE.dim 104 | BEAM-DIMAP 105 | 106 | 107 | 108 | Write 109 | 110 | 111 | 112 | 113 | OUTPUTIFGFOLDER/OUTPUTFILE.dim 114 | BEAM-DIMAP 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | -------------------------------------------------------------------------------- /graphs/topsar_coreg_ifg_computation_extDEM.xml: -------------------------------------------------------------------------------- 1 | 2 | 1.0 3 | 4 | Read 5 | 6 | 7 | MASTER 8 | 9 | 10 | 11 | Read 12 | 13 | 14 | SECONDARY 15 | 16 | 17 | 18 | Back-Geocoding 19 | 20 | 21 | 22 | 23 | 24 | External DEM 25 | BILINEAR_INTERPOLATION 26 | EXTERNALDEM 27 | 0.0 28 | BILINEAR_INTERPOLATION 29 | false 30 | false 31 | false 32 | false 33 | 34 | 35 | 36 | Enhanced-Spectral-Diversity 37 | 38 | 39 | 40 | 41 | 512 42 | 512 43 | 16 44 | 16 45 | 128 46 | 0.1 47 | 0.15 48 | 10 49 | false 50 | 0.0 51 | false 52 | 0.0 53 | 54 | 55 | 56 | Interferogram 57 | 58 | 59 | 60 | 61 | true 62 | 5 63 | 501 64 | 3 65 | false 66 | 2 67 | 10 68 | true 69 | false 70 | SRTM 1Sec HGT 71 | 72 | 0.0 73 | 74 | 100 75 | true 76 | true 77 | 78 | 79 | 80 | TOPSAR-Deburst 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | TOPSAR-Deburst 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | Write 99 | 100 | 101 | 102 | 103 | OUTPUTCOREGFOLDER/OUTPUTFILE.dim 104 | BEAM-DIMAP 105 | 106 | 107 | 108 | Write 109 | 110 | 111 | 112 | 113 | OUTPUTIFGFOLDER/OUTPUTFILE.dim 114 | BEAM-DIMAP 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | -------------------------------------------------------------------------------- /bin/stripmap_step_3_ifg_sar.py: -------------------------------------------------------------------------------- 1 | ### Python script to use SNAP as InSAR processor for TSX/TDX processing compatible with StaMPS PSI processing 2 | # Author: Jonas Ziemer, adapted from Jose Manuel Delgado Blasco (snap2stamps package) 3 | # Date: 01/01/2023 4 | # Version: 2.1, Python 3.9 5 | 6 | # Step 1: unzip downloaded TSX scenes (.tar; .tar.gz) 7 | # Step 2: preparing secondaries in folder structure 8 | # Step 3: subset TSX scenes 9 | # Step 4: Coregistration 10 | # Step 5: Interferogram generation 11 | # Step 6: StaMPS export 12 | 13 | 14 | import os 15 | import sys 16 | import glob 17 | import subprocess 18 | import shlex 19 | import time 20 | import warnings 21 | import argparse 22 | import configparser 23 | 24 | warnings.filterwarnings('ignore') 25 | sys.stdout.flush() 26 | 27 | parser = argparse.ArgumentParser(description='This script runs the Interferogram computation and TopoPhase removal') 28 | parser.add_argument("--ProjFile","-F", type=str) 29 | 30 | args = parser.parse_args() 31 | if not args.ProjFile: 32 | print("No Input File detected") 33 | sys.exit(-1) 34 | else: 35 | configfile = args.ProjFile 36 | 37 | bar_message='\n#####################################################################\n' 38 | 39 | os.environ["LD_LIBRARY_PATH"] ="." 40 | # Getting configuration variables from inputfile 41 | config = configparser.ConfigParser() 42 | config.read(configfile) 43 | 44 | PROJECT=config['PROJECT_DEFINITION'].get('PROJECTFOLDER') 45 | GRAPH=config['PROJECT_DEFINITION'].get('GRAPHSFOLDER') 46 | 47 | OVERWRITE=config['PROC_OPTIONS'].get('OVERWRITE') 48 | SMARTHDD=config['PROC_OPTIONS'].get('SMARTHDD') 49 | 50 | extDEM=config['PROC_PARAMETERS'].get('EXTDEM') 51 | 52 | CACHE=config['COMPUTING_RESOURCES'].get('CACHE') 53 | CPU=config['COMPUTING_RESOURCES'].get('CPU') 54 | 55 | ################################################################### 56 | ## GETTING PATH to gpt executable 57 | SNAPFOLDER=config['SNAP_GPT'].get('SNAP_INSTALLATION_FOLDER') 58 | GPT=os.path.join(SNAPFOLDER,'bin','gpt') 59 | if os.name == 'nt': 60 | GPT=os.path.join(SNAPFOLDER,'bin','gpt.exe') 61 | 62 | ############################################################################ 63 | # Checking GPT 64 | if not os.path.exists(GPT): 65 | errormessage="GPT executable not found in "+GPT+".Processing aborted" 66 | print(errormessage) 67 | sys.exit(errormessage) 68 | 69 | ###################################################################################### 70 | ####################### TSX-SAR Interferogram generation ############################# 71 | ###################################################################################### 72 | # Folders involved in this processing step 73 | outputcoregfolder=os.path.join(PROJECT,'coreg') 74 | outputifgfolder=os.path.join(PROJECT,'ifg') 75 | logfolder=os.path.join(PROJECT,'logs') 76 | 77 | if not os.path.exists(outputifgfolder): 78 | os.makedirs(outputifgfolder) 79 | if not os.path.exists(logfolder): 80 | os.makedirs(logfolder) 81 | 82 | outlog=os.path.join(logfolder,'ifg_proc_stdout.log') 83 | 84 | # Original Snap graph and replaced Snap graph for Interferogram generation 85 | if extDEM=='': 86 | graphxml=os.path.join(GRAPH,'stripmap_Interferogram_TopoPhase.xml') 87 | else: 88 | graphxml=os.path.join(GRAPH,'stripmap_Interferogram_TopoPhase_extDEM.xml') 89 | print(graphxml) 90 | graph2run=os.path.join(GRAPH,'ifg_2run.xml') 91 | 92 | out_file = open(outlog, 'a') 93 | err_file=out_file 94 | 95 | # Processing layout 96 | print(bar_message) 97 | out_file.write(bar_message) 98 | message='## Interferogram generation started:\n' 99 | print(message) 100 | out_file.write(message) 101 | print(bar_message) 102 | out_file.write(bar_message) 103 | k=0 104 | timeStarted_global = time.time() 105 | # Iterate trough all files in the coregfolder 106 | for dimfile in glob.iglob(outputcoregfolder + '/*.dim'): 107 | print(dimfile) 108 | k=k+1 109 | # Create name of the output ifg file 110 | head, tail = os.path.split(os.path.join(outputcoregfolder, dimfile)) 111 | message='['+str(k)+'] Processing coreg file: '+tail+'\n' 112 | print(message) 113 | out_file.write(message) 114 | outputname=tail[0:17]+'.dim' 115 | with open(graphxml, 'r') as file : 116 | filedata = file.read() 117 | # Replace the target string and generate a new file with replaced names for use in SNAP 118 | filedata = filedata.replace('COREGFILE',dimfile) 119 | filedata = filedata.replace('EXTERNALDEM', extDEM) 120 | filedata = filedata.replace('OUTPUTIFGFOLDER',outputifgfolder) 121 | filedata = filedata.replace('OUTPUTFILE',outputname) 122 | with open(graph2run, 'w') as file: 123 | file.write(filedata) 124 | args = [ GPT, graph2run, '-c', CACHE, '-q', CPU] 125 | # Launch the processing 126 | process = subprocess.Popen(args, stdout=subprocess.PIPE,stderr=subprocess.STDOUT) 127 | timeStarted = time.time() 128 | stdout = process.communicate()[0] 129 | print('SNAP STDOUT:{}'.format(stdout)) 130 | # Get execution time 131 | timeDelta = time.time() - timeStarted 132 | print('['+str(k)+'] Finished process in '+str(timeDelta)+' seconds.') 133 | out_file.write('['+str(k)+'] Finished process in '+str(timeDelta)+' seconds.\n') 134 | if process.returncode != 0 : 135 | message='Error computing with interferogram generation of coreg file '+str(dimfile) 136 | err_file.write(message+'\n') 137 | else: 138 | message='Interferogram computation for data '+str(outputname)+' successfully completed.\n' 139 | print(message) 140 | out_file.write(message) 141 | print(bar_message) 142 | out_file.write(bar_message) 143 | timeDelta_global = time.time() - timeStarted_global 144 | print('Finished interferogram generation in ' + str(timeDelta_global) + ' seconds.\n') 145 | out_file.close() 146 | -------------------------------------------------------------------------------- /bin/stripmap_step_2_coreg_sar.py: -------------------------------------------------------------------------------- 1 | ### Python script to use SNAP as InSAR processor for TSX/TDX processing compatible with StaMPS PSI processing 2 | # Author: Jonas Ziemer, adapted from Jose Manuel Delgado Blasco (snap2stamps package) 3 | # Date: 01/01/2023 4 | # Version: 2.1, Python 3.9 5 | 6 | # Step 1: unzip downloaded TSX scenes (.tar; .tar.gz) 7 | # Step 2: preparing secondaries in folder structure 8 | # Step 3: subset TSX scenes 9 | # Step 4: Coregistration 10 | # Step 5: Interferogram generation 11 | # Step 6: StaMPS export 12 | 13 | 14 | import os 15 | import sys 16 | import glob 17 | import subprocess 18 | import shlex 19 | import time 20 | import warnings 21 | import argparse 22 | import configparser 23 | 24 | warnings.filterwarnings('ignore') 25 | sys.stdout.flush() 26 | 27 | parser = argparse.ArgumentParser(description='This script runs the DEM Assisted coregstration using External DEM') 28 | parser.add_argument("--ProjFile","-F", type=str) 29 | 30 | args = parser.parse_args() 31 | if not args.ProjFile: 32 | print("No Input File detected") 33 | sys.exit(-1) 34 | else: 35 | configfile = args.ProjFile 36 | 37 | bar_message='\n#####################################################################\n' 38 | 39 | os.environ["LD_LIBRARY_PATH"] ="." 40 | # Getting configuration variables from inputfile 41 | config = configparser.ConfigParser() 42 | config.read(configfile) 43 | 44 | PROJECT=config['PROJECT_DEFINITION'].get('PROJECTFOLDER') 45 | GRAPH=config['PROJECT_DEFINITION'].get('GRAPHSFOLDER') 46 | 47 | OVERWRITE=config['PROC_OPTIONS'].get('OVERWRITE') 48 | SMARTHDD=config['PROC_OPTIONS'].get('SMARTHDD') 49 | 50 | POLARISATION=config['PROC_PARAMETERS'].get('POLARISATION') 51 | MASTERFOLDER=config['PROC_PARAMETERS'].get('MASTER') 52 | extDEM=config['PROC_PARAMETERS'].get('EXTDEM') 53 | masterfolder=MASTERFOLDER 54 | CACHE=config['COMPUTING_RESOURCES'].get('CACHE') 55 | CPU=config['COMPUTING_RESOURCES'].get('CPU') 56 | ################################################################### 57 | ## GETTING PATH to gpt executable 58 | SNAPFOLDER=config['SNAP_GPT'].get('SNAP_INSTALLATION_FOLDER') 59 | GPT=os.path.join(SNAPFOLDER,'bin','gpt') 60 | if os.name == 'nt': 61 | GPT=os.path.join(SNAPFOLDER,'bin','gpt.exe') 62 | 63 | 64 | ############################################################################ 65 | # Checking GPT 66 | if not os.path.exists(GPT): 67 | errormessage="GPT executable not found in "+GPT+".Processing aborted" 68 | print(errormessage) 69 | sys.exit(errormessage) 70 | 71 | ###################################################################################### 72 | ############################## TSX-SAR Coregistration ################################ 73 | ###################################################################################### 74 | # Folders involved in this processing step 75 | subsetfolder=os.path.join(PROJECT,'subset') 76 | outputcoregfolder=os.path.join(PROJECT,'coreg') 77 | logfolder=os.path.join(PROJECT,'logs') 78 | 79 | if not os.path.exists(outputcoregfolder): 80 | os.makedirs(outputcoregfolder) 81 | if not os.path.exists(logfolder): 82 | os.makedirs(logfolder) 83 | 84 | outlog=os.path.join(logfolder,'coreg_proc_stdout.log') 85 | 86 | # Original Snap graph and replaced Snap graph for Coregistration 87 | if extDEM=='': 88 | graphxml=os.path.join(GRAPH,'stripmap_DEM_Assisted_Coregistration.xml') 89 | else: 90 | graphxml=os.path.join(GRAPH,'stripmap_DEM_Assisted_Coregistration_extDEM.xml') 91 | print(graphxml) 92 | graph2run=os.path.join(GRAPH,'coreg_2run.xml') 93 | 94 | out_file = open(outlog, 'a') 95 | err_file=out_file 96 | 97 | # Processing layout 98 | print(bar_message) 99 | out_file.write(bar_message) 100 | message='## Coregistration started:\n' 101 | print(message) 102 | out_file.write(message) 103 | print(bar_message) 104 | out_file.write(bar_message) 105 | k=0 106 | timeStarted_global = time.time() 107 | # Iterate trough all files in the subsetfolder 108 | for dimfile in glob.iglob(subsetfolder + '/*.dim'): 109 | print(dimfile) 110 | k=k+1 111 | # Create name of the output coreg file 112 | head, tail = os.path.split(os.path.join(subsetfolder, dimfile)) 113 | message='['+str(k)+'] Processing secondaries file: '+tail+'\n' 114 | print(message) 115 | out_file.write(message) 116 | head , tailm = os.path.split(masterfolder) 117 | outputname=tailm[0:8]+'_'+tail[0:8]+'.dim' 118 | print(outputname) 119 | with open(graphxml, 'r') as file : 120 | filedata = file.read() 121 | # Replace the target string and generate a new file with replaced names for use in SNAP 122 | filedata = filedata.replace('MASTER',masterfolder) 123 | filedata = filedata.replace('SECONDARY',dimfile) 124 | filedata = filedata.replace('EXTERNALDEM',extDEM) 125 | filedata = filedata.replace('OUTPUTCOREGFOLDER',outputcoregfolder) 126 | filedata = filedata.replace('OUTPUTFILE',outputname) 127 | with open(graph2run, 'w') as file: 128 | file.write(filedata) 129 | args = [ GPT, graph2run, '-c', CACHE, '-q', CPU] 130 | # Launch the processing 131 | process = subprocess.Popen(args, stdout=subprocess.PIPE,stderr=subprocess.STDOUT) 132 | timeStarted = time.time() 133 | stdout = process.communicate()[0] 134 | print('SNAP STDOUT:{}'.format(stdout)) 135 | # Get execution time 136 | timeDelta = time.time() - timeStarted 137 | print('['+str(k)+'] Finished process in '+str(timeDelta)+' seconds.') 138 | out_file.write('['+str(k)+'] Finished process in '+str(timeDelta)+' seconds.\n') 139 | if process.returncode != 0 : 140 | message='Error computing with coregistration of splitted secondaries '+str(dimfile) 141 | err_file.write(message+'\n') 142 | else: 143 | message='Coregistration for data '+str(outputname)+' successfully completed.\n' 144 | print(message) 145 | out_file.write(message) 146 | print(bar_message) 147 | out_file.write(bar_message) 148 | timeDelta_global = time.time() - timeStarted_global 149 | print('Finished coregistration in ' + str(timeDelta_global) + ' seconds.\n') 150 | out_file.close() 151 | -------------------------------------------------------------------------------- /graphs/topsar_coreg_ifg_computation_subset_noESD.xml: -------------------------------------------------------------------------------- 1 | 2 | 1.0 3 | 4 | Read 5 | 6 | 7 | MASTER 8 | 9 | 10 | 11 | Read 12 | 13 | 14 | SECONDARY 15 | 16 | 17 | 18 | Back-Geocoding 19 | 20 | 21 | 22 | 23 | 24 | SRTM 1Sec HGT 25 | BILINEAR_INTERPOLATION 26 | 27 | 0.0 28 | BILINEAR_INTERPOLATION 29 | false 30 | false 31 | false 32 | false 33 | 34 | 35 | 36 | Interferogram 37 | 38 | 39 | 40 | 41 | true 42 | 5 43 | 501 44 | 3 45 | false 46 | 2 47 | 10 48 | true 49 | false 50 | SRTM 1Sec HGT 51 | 52 | 0.0 53 | 54 | 55 | true 56 | true 57 | 58 | 59 | 60 | TOPSAR-Deburst 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | TOPSAR-Deburst 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | Write 79 | 80 | 81 | 82 | 83 | OUTPUTCOREGFOLDER/OUTPUTFILE.dim 84 | BEAM-DIMAP 85 | 86 | 87 | 88 | TopoPhaseRemoval 89 | 90 | 91 | 92 | 93 | 3 94 | SRTM 1Sec HGT 95 | 96 | 0.0 97 | 100 98 | true 99 | true 100 | true 101 | 102 | 103 | 104 | Subset 105 | 106 | 107 | 108 | 109 | 110 | 0,0,24608,2844 111 | POLYGON 112 | 1 113 | 1 114 | false 115 | 116 | true 117 | 118 | 119 | 120 | Subset 121 | 122 | 123 | 124 | 125 | 126 | 0,0,24608,2844 127 | POLYGON 128 | 1 129 | 1 130 | false 131 | 132 | true 133 | 134 | 135 | 136 | Write 137 | 138 | 139 | 140 | 141 | OUTPUTIFGFOLDER/OUTPUTFILE.dim 142 | BEAM-DIMAP 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | -------------------------------------------------------------------------------- /graphs/topsar_coreg_ifg_computation_subset_noESD_extDEM.xml: -------------------------------------------------------------------------------- 1 | 2 | 1.0 3 | 4 | Read 5 | 6 | 7 | MASTER 8 | 9 | 10 | 11 | Read 12 | 13 | 14 | SECONDARY 15 | 16 | 17 | 18 | Back-Geocoding 19 | 20 | 21 | 22 | 23 | 24 | External DEM 25 | BILINEAR_INTERPOLATION 26 | EXTERNALDEM 27 | 0.0 28 | BILINEAR_INTERPOLATION 29 | false 30 | false 31 | false 32 | false 33 | 34 | 35 | 36 | Interferogram 37 | 38 | 39 | 40 | 41 | true 42 | 5 43 | 501 44 | 3 45 | false 46 | 2 47 | 10 48 | true 49 | false 50 | SRTM 1Sec HGT 51 | 52 | 0.0 53 | 54 | 55 | true 56 | true 57 | 58 | 59 | 60 | TOPSAR-Deburst 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | TOPSAR-Deburst 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | Write 79 | 80 | 81 | 82 | 83 | OUTPUTCOREGFOLDER/OUTPUTFILE.dim 84 | BEAM-DIMAP 85 | 86 | 87 | 88 | TopoPhaseRemoval 89 | 90 | 91 | 92 | 93 | 3 94 | External DEM 95 | EXTERNALDEM 96 | 0.0 97 | 100 98 | true 99 | true 100 | true 101 | 102 | 103 | 104 | Subset 105 | 106 | 107 | 108 | 109 | 110 | 0,0,24608,2844 111 | POLYGON 112 | 1 113 | 1 114 | false 115 | 116 | true 117 | 118 | 119 | 120 | Subset 121 | 122 | 123 | 124 | 125 | 126 | 0,0,24608,2844 127 | POLYGON 128 | 1 129 | 1 130 | false 131 | 132 | true 133 | 134 | 135 | 136 | Write 137 | 138 | 139 | 140 | 141 | OUTPUTIFGFOLDER/OUTPUTFILE.dim 142 | BEAM-DIMAP 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | -------------------------------------------------------------------------------- /bin/stripmap_step_1_subset_sar.py: -------------------------------------------------------------------------------- 1 | ### Python script to use SNAP as InSAR processor for TSX/TDX processing compatible with StaMPS PSI processing 2 | # Author: Jonas Ziemer, adapted from Jose Manuel Delgado Blasco (snap2stamps package) 3 | # Date: 01/01/2023 4 | # Version: 2.1, Python 3.9 5 | 6 | # Step 1: unzip downloaded TSX scenes (.tar; .tar.gz) 7 | # Step 2: preparing secondaries in folder structure 8 | # Step 3: subset TSX scenes 9 | # Step 4: Coregistration 10 | # Step 5: Interferogram generation 11 | # Step 6: StaMPS export 12 | 13 | 14 | import os 15 | import sys 16 | import glob 17 | import subprocess 18 | import shlex 19 | import time 20 | import warnings 21 | import argparse 22 | import configparser 23 | 24 | inputfile = sys.argv[1] 25 | 26 | warnings.filterwarnings('ignore') 27 | sys.stdout.flush() 28 | 29 | parser = argparse.ArgumentParser(description='This script runs the spatial subset using defined AOI') 30 | parser.add_argument("--ProjFile","-F", type=str) 31 | 32 | args = parser.parse_args() 33 | if not args.ProjFile: 34 | print("No Input File detected") 35 | sys.exit(-1) 36 | else: 37 | configfile = args.ProjFile 38 | inputfile=configfile 39 | 40 | bar_message='\n#####################################################################\n' 41 | # Setting LD_LIBRARY_PATH for SNAP 42 | #os.environ["LD_LIBRARY_PATH"] = os.getcwd() 43 | os.environ["LD_LIBRARY_PATH"] ="." 44 | # Getting configuration variables from inputfile 45 | config = configparser.ConfigParser() 46 | config.read(configfile) 47 | 48 | PROJECT=config['PROJECT_DEFINITION'].get('PROJECTFOLDER') 49 | GRAPH=config['PROJECT_DEFINITION'].get('GRAPHSFOLDER') 50 | 51 | OVERWRITE=config['PROC_OPTIONS'].get('OVERWRITE') 52 | SMARTHDD=config['PROC_OPTIONS'].get('SMARTHDD') 53 | 54 | POLARISATION=config['PROC_PARAMETERS'].get('POLARISATION') 55 | MASTERFOLDER=config['PROC_PARAMETERS'].get('MASTER') 56 | masterfolder=MASTERFOLDER 57 | CACHE=config['COMPUTING_RESOURCES'].get('CACHE') 58 | CPU=config['COMPUTING_RESOURCES'].get('CPU') 59 | ###################################################################################### 60 | ## GETTING AOI DEFINITION 61 | aoi_mode=config['AOI_DEFINITION'].get('AOI_MODE') 62 | print(aoi_mode) 63 | if aoi_mode == 'WKT': 64 | polygon=config['AOI_DEFINITION'].get('WKT') 65 | elif aoi_mode == 'BBOX': 66 | LONMIN=config['AOI_DEFINITION'].get('LONMIN') 67 | LATMIN=config['AOI_DEFINITION'].get('LATMIN') 68 | LONMAX=config['AOI_DEFINITION'].get('LONMAX') 69 | LATMAX=config['AOI_DEFINITION'].get('LATMAX') 70 | polygon='POLYGON (('+LONMIN+' '+LATMIN+','+LONMAX+' '+LATMIN+','+LONMAX+' '+LATMAX+','+LONMIN+' '+LATMAX+','+LONMIN+' '+LATMIN+'))' 71 | elif aoi_mode == 'SHP' or aoi_mode == 'GeoJSON' or aoi_mode == 'KML': 72 | AOIFile=config['AOI_DEFINITION'].get('AOI_FILE') 73 | if aoi_mode != 'KML': 74 | gdf=gpd.read_file(AOIFile) 75 | else: 76 | import fiona 77 | fiona.drvsupport.supported_drivers['KML'] = 'rw' 78 | gdf = gpd.read_file(AOIFile, driver='KML') 79 | #polygon=str(gdf['geometry'].wkt) 80 | # from shapely import wkt 81 | # polygon = wkt.dumps(gdf['geometry'][0]) 82 | polygon = str(gdf.envelope[0]) 83 | # print(polygon) 84 | else: 85 | print('Wrong AOI_MODE parameter! Please revise the configuration file') 86 | sys.exit() 87 | 88 | print( polygon) 89 | ################################################################### 90 | ## GETTING PATH to gpt executable 91 | SNAPFOLDER=config['SNAP_GPT'].get('SNAP_INSTALLATION_FOLDER') 92 | GPT=os.path.join(SNAPFOLDER,'bin','gpt') 93 | if os.name == 'nt': 94 | GPT=os.path.join(SNAPFOLDER,'bin','gpt.exe') 95 | 96 | 97 | ############################################################################# 98 | ### TOPSAR Splitting (Assembling) and Apply Orbit section #### 99 | ############################################################################ 100 | # Checking GPT 101 | if not os.path.exists(GPT): 102 | errormessage="GPT executable not found in "+GPT+".Processing aborted" 103 | print(errormessage) 104 | sys.exit(errormessage) 105 | 106 | 107 | ###################################################################################### 108 | ################################### TSX Subsetting ################################### 109 | ##### Dont forget to move your master subset into a newly created master folder! ##### 110 | # Folders involved in this processing step 111 | secondariesplittedfolder=PROJECT+'/secondaries' 112 | outputsubsetfolder=PROJECT+'/subset' 113 | logfolder=PROJECT+'/logs' 114 | 115 | if not os.path.exists(outputsubsetfolder): 116 | os.makedirs(outputsubsetfolder) 117 | if not os.path.exists(logfolder): 118 | os.makedirs(logfolder) 119 | 120 | outlog=logfolder+'/subset_stdout.log' 121 | 122 | # Original Snap graph and replaced Snap graph for subsettting 123 | graphxml=GRAPH+'/stripmap_TSX_Subset.xml' 124 | print(graphxml) 125 | graph2run=GRAPH+'/subset_2run.xml' 126 | 127 | out_file = open(outlog, 'a') 128 | err_file=out_file 129 | 130 | # Processing layout 131 | print(bar_message) 132 | out_file.write(bar_message) 133 | message='## Subsetting started:\n' 134 | print(message) 135 | out_file.write(message) 136 | print(bar_message) 137 | out_file.write(bar_message) 138 | k=0 139 | timeStarted_global = time.time() 140 | # Iterate trough all files in the secondariesfolder 141 | for xmlfile in glob.iglob(secondariesplittedfolder + '/*/*/*.xml'): 142 | print(xmlfile) 143 | k=k+1 144 | # Create name of the output subset file 145 | head, tail = os.path.split(os.path.join(secondariesplittedfolder, xmlfile)) 146 | message='['+str(k)+'] Processing subset file: '+tail+'\n' 147 | print(message) 148 | out_file.write(message) 149 | outputname=tail[28:36]+'_sub.dim' 150 | with open(graphxml, 'r') as file : 151 | filedata = file.read() 152 | # Replace the target string and generate a new file with replaced names for use in SNAP 153 | filedata = filedata.replace('INPUTXML',xmlfile) 154 | filedata = filedata.replace('OUTPUTSUBSETFOLDER',outputsubsetfolder) 155 | filedata = filedata.replace('OUTPUTFILE',outputname) 156 | filedata = filedata.replace('POLYGON',polygon) 157 | with open(graph2run, 'w') as file: 158 | file.write(filedata) 159 | args = [ GPT, graph2run, '-c', CACHE, '-q', CPU] 160 | # Launch the processing 161 | process = subprocess.Popen(args, stdout=subprocess.PIPE,stderr=subprocess.STDOUT) 162 | timeStarted = time.time() 163 | stdout = process.communicate()[0] 164 | print('SNAP STDOUT:{}'.format(stdout)) 165 | # Get execution time 166 | timeDelta = time.time() - timeStarted 167 | print('['+str(k)+'] Finished process in '+str(timeDelta)+' seconds.') 168 | out_file.write('['+str(k)+'] Finished process in '+str(timeDelta)+' seconds.\n') 169 | if process.returncode != 0 : 170 | message='Error computing with subset of splitted secondaries '+str(xmlfile) 171 | err_file.write(message+'\n') 172 | else: 173 | message='Subsetting for data '+str(outputname)+' successfully completed.\n' 174 | print(message) 175 | out_file.write(message) 176 | print(bar_message) 177 | out_file.write(bar_message) 178 | timeDelta_global = time.time() - timeStarted_global 179 | print('Finished subsetting in ' + str(timeDelta_global) + ' seconds.\n') 180 | out_file.close() 181 | 182 | -------------------------------------------------------------------------------- /graphs/topsar_coreg_ifg_computation_subset.xml: -------------------------------------------------------------------------------- 1 | 2 | 1.0 3 | 4 | Read 5 | 6 | 7 | MASTER 8 | 9 | 10 | 11 | Read 12 | 13 | 14 | SECONDARY 15 | 16 | 17 | 18 | Back-Geocoding 19 | 20 | 21 | 22 | 23 | 24 | SRTM 1Sec HGT 25 | BILINEAR_INTERPOLATION 26 | 27 | 0.0 28 | BILINEAR_INTERPOLATION 29 | false 30 | false 31 | false 32 | false 33 | 34 | 35 | 36 | Enhanced-Spectral-Diversity 37 | 38 | 39 | 40 | 41 | 512 42 | 512 43 | 16 44 | 16 45 | 128 46 | 0.1 47 | 0.15 48 | 10 49 | false 50 | 0.0 51 | false 52 | 0.0 53 | 54 | 55 | 56 | Interferogram 57 | 58 | 59 | 60 | 61 | true 62 | 5 63 | 501 64 | 3 65 | false 66 | 2 67 | 10 68 | true 69 | false 70 | SRTM 1Sec HGT 71 | 72 | 0.0 73 | 74 | 75 | true 76 | true 77 | 78 | 79 | 80 | TOPSAR-Deburst 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | TOPSAR-Deburst 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | Write 99 | 100 | 101 | 102 | 103 | OUTPUTCOREGFOLDER/OUTPUTFILE.dim 104 | BEAM-DIMAP 105 | 106 | 107 | 108 | TopoPhaseRemoval 109 | 110 | 111 | 112 | 113 | 3 114 | SRTM 1Sec HGT 115 | 116 | 0.0 117 | 100 118 | true 119 | true 120 | true 121 | 122 | 123 | 124 | Subset 125 | 126 | 127 | 128 | 129 | 130 | 0,0,24608,2844 131 | POLYGON 132 | 1 133 | 1 134 | false 135 | 136 | true 137 | 138 | 139 | 140 | Subset 141 | 142 | 143 | 144 | 145 | 146 | 0,0,24608,2844 147 | POLYGON 148 | 1 149 | 1 150 | false 151 | 152 | true 153 | 154 | 155 | 156 | Write 157 | 158 | 159 | 160 | 161 | OUTPUTIFGFOLDER/OUTPUTFILE.dim 162 | BEAM-DIMAP 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | -------------------------------------------------------------------------------- /graphs/topsar_coreg_ifg_computation_subset_extDEM.xml: -------------------------------------------------------------------------------- 1 | 2 | 1.0 3 | 4 | Read 5 | 6 | 7 | MASTER 8 | 9 | 10 | 11 | Read 12 | 13 | 14 | SECONDARY 15 | 16 | 17 | 18 | Back-Geocoding 19 | 20 | 21 | 22 | 23 | 24 | External DEM 25 | BILINEAR_INTERPOLATION 26 | EXTERNALDEM 27 | 0.0 28 | BILINEAR_INTERPOLATION 29 | false 30 | false 31 | false 32 | false 33 | 34 | 35 | 36 | Enhanced-Spectral-Diversity 37 | 38 | 39 | 40 | 41 | 512 42 | 512 43 | 16 44 | 16 45 | 128 46 | 0.1 47 | 0.15 48 | 10 49 | false 50 | 0.0 51 | false 52 | 0.0 53 | 54 | 55 | 56 | Interferogram 57 | 58 | 59 | 60 | 61 | true 62 | 5 63 | 501 64 | 3 65 | false 66 | 2 67 | 10 68 | true 69 | false 70 | SRTM 1Sec HGT 71 | 72 | 0.0 73 | 74 | 75 | true 76 | true 77 | 78 | 79 | 80 | TOPSAR-Deburst 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | TOPSAR-Deburst 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | Write 99 | 100 | 101 | 102 | 103 | OUTPUTCOREGFOLDER/OUTPUTFILE.dim 104 | BEAM-DIMAP 105 | 106 | 107 | 108 | TopoPhaseRemoval 109 | 110 | 111 | 112 | 113 | 3 114 | External DEM 115 | EXTERNALDEM 116 | 0.0 117 | 100 118 | true 119 | true 120 | true 121 | 122 | 123 | 124 | Subset 125 | 126 | 127 | 128 | 129 | 130 | 0,0,24608,2844 131 | POLYGON 132 | 1 133 | 1 134 | false 135 | 136 | true 137 | 138 | 139 | 140 | Subset 141 | 142 | 143 | 144 | 145 | 146 | 0,0,24608,2844 147 | POLYGON 148 | 1 149 | 1 150 | false 151 | 152 | true 153 | 154 | 155 | 156 | Write 157 | 158 | 159 | 160 | 161 | OUTPUTIFGFOLDER/OUTPUTFILE.dim 162 | BEAM-DIMAP 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | -------------------------------------------------------------------------------- /bin/topsar_step_1_splitting_master_multi_IW.py: -------------------------------------------------------------------------------- 1 | ### Python script to use SNAP as InSAR processor compatible with StaMPS PSI processing 2 | # Author Jose Manuel Delgado Blasco 3 | # Date: 21/06/2018 4 | # Updated: 01/06/2023 5 | # Version: 2.0 6 | 7 | # Step 0 : preparing secondary images in folder structure 8 | # Step 1 : Master TOPSAR Splitting (Assembling) and Apply Orbit 9 | # Step 2 : TOPSAR Splitting (Assembling) and Apply Orbit of Secondary Images 10 | # Step 3 : Coregistration and Interferogram generation 11 | # Step 4 : StaMPS export 12 | # Step 5 : Plotting secondaries and interferometric phase 13 | 14 | # Added option for CACHE and CPU specification by user 15 | # Planned support for DEM selection and ORBIT type selection 16 | 17 | 18 | import configparser 19 | import argparse 20 | import warnings 21 | import io 22 | import os 23 | from pathlib import Path 24 | import sys 25 | import glob 26 | from subprocess import PIPE, Popen, STDOUT 27 | import shlex 28 | import time 29 | 30 | import geopandas as gpd 31 | 32 | sys.stdout.flush() 33 | inputfile = sys.argv[1] 34 | warnings.filterwarnings('ignore') 35 | 36 | parser = argparse.ArgumentParser(description='This script splits the master Sentinel-1 image') 37 | parser.add_argument("--ProjFile","-F", type=str) 38 | 39 | args = parser.parse_args() 40 | if not args.ProjFile: 41 | print("No Input File detected") 42 | sys.exit(-1) 43 | else: 44 | configfile = args.ProjFile 45 | 46 | 47 | bar_message='\n#####################################################################\n' 48 | # Setting LD_LIBRARY_PATH for SNAP 49 | #os.environ["LD_LIBRARY_PATH"] = os.getcwd() 50 | os.environ["LD_LIBRARY_PATH"] ="." 51 | # Getting configuration variables from inputfile 52 | config = configparser.ConfigParser() 53 | config.read(configfile) 54 | 55 | PROJECT=config['PROJECT_DEFINITION'].get('PROJECTFOLDER') 56 | GRAPH=config['PROJECT_DEFINITION'].get('GRAPHSFOLDER') 57 | 58 | OVERWRITE=config['PROC_OPTIONS'].get('OVERWRITE') 59 | SMARTHDD=config['PROC_OPTIONS'].get('SMARTHDD') 60 | 61 | POLARISATION=config['PROC_PARAMETERS'].get('POLARISATION') 62 | MASTERFOLDER=config['PROC_PARAMETERS'].get('MASTER') 63 | masterfolder=MASTERFOLDER 64 | CACHE=config['COMPUTING_RESOURCES'].get('CACHE') 65 | CPU=config['COMPUTING_RESOURCES'].get('CPU') 66 | 67 | ######################################################### 68 | ## GETTING AOI DEFINITION 69 | aoi_mode=config['AOI_DEFINITION'].get('AOI_MODE') 70 | print(aoi_mode) 71 | if aoi_mode == 'WKT': 72 | polygon=config['AOI_DEFINITION'].get('WKT') 73 | elif aoi_mode == 'BBOX': 74 | LONMIN=config['AOI_DEFINITION'].get('LONMIN') 75 | LATMIN=config['AOI_DEFINITION'].get('LATMIN') 76 | LONMAX=config['AOI_DEFINITION'].get('LONMAX') 77 | LATMAX=config['AOI_DEFINITION'].get('LATMAX') 78 | polygon='POLYGON (('+LONMIN+' '+LATMIN+','+LONMAX+' '+LATMIN+','+LONMAX+' '+LATMAX+','+LONMIN+' '+LATMAX+','+LONMIN+' '+LATMIN+'))' 79 | elif aoi_mode == 'SHP' or aoi_mode == 'GeoJSON' or aoi_mode == 'KML': 80 | AOIFile=config['AOI_DEFINITION'].get('AOI_FILE') 81 | if aoi_mode != 'KML': 82 | gdf=gpd.read_file(AOIFile) 83 | else: 84 | import fiona 85 | fiona.drvsupport.supported_drivers['KML'] = 'rw' 86 | gdf = gpd.read_file(AOIFile, driver='KML') 87 | #polygon=str(gdf['geometry'].wkt) 88 | # from shapely import wkt 89 | # polygon = wkt.dumps(gdf['geometry'][0]) 90 | polygon = str(gdf.envelope[0]) 91 | # print(polygon) 92 | else: 93 | print('Wrong AOI_MODE parameter! Please revise the configuration file') 94 | sys.exit() 95 | 96 | print( polygon) 97 | 98 | ################################################################### 99 | ## GETTING PATH to gpt executable 100 | SNAPFOLDER=config['SNAP_GPT'].get('SNAP_INSTALLATION_FOLDER') 101 | GPT=os.path.join(SNAPFOLDER,'bin','gpt') 102 | if os.name == 'nt': 103 | GPT=os.path.join(SNAPFOLDER,'bin','gpt.exe') 104 | 105 | 106 | ############################################################################# 107 | ### TOPSAR Splitting (Assembling) and Apply Orbit section #### 108 | ############################################################################ 109 | # Checking GPT 110 | if not os.path.exists(GPT): 111 | errormessage="GPT executable not found in "+GPT+".Processing aborted" 112 | print(errormessage) 113 | sys.exit(errormessage) 114 | 115 | # Initialising set-up 116 | #masterfolder=os.path.join(PROJECT,'master') 117 | splitmasterfolder=os.path.join(PROJECT,'MasterSplit') 118 | logfolder=os.path.join(PROJECT,'logs') 119 | graphfolder=os.path.join(PROJECT,'graphs') 120 | 121 | if not os.path.exists(splitmasterfolder): 122 | os.makedirs(splitmasterfolder) 123 | if not os.path.exists(logfolder): 124 | os.makedirs(logfolder) 125 | if not os.path.exists(graphfolder): 126 | os.makedirs(graphfolder) 127 | 128 | graph2run=os.path.join(graphfolder,'splitgraph2run.xml') 129 | outlog=os.path.join(logfolder,'splitmaster.log') 130 | out_file = open(outlog, 'a') 131 | err_file=out_file 132 | 133 | print (bar_message) 134 | out_file.write(bar_message) 135 | message='## TOPSAR Splitting and Apply Orbit\n' 136 | print (message) 137 | out_file.write(message) 138 | print (bar_message) 139 | out_file.write(bar_message) 140 | 141 | files = glob.glob(masterfolder + '/*.zip') 142 | filename=os.path.basename(files[0]) 143 | acdatefolder=filename[17:25] 144 | if len(files)==0: 145 | files = glob.glob(os.path.join(masterfolder, acdatefolder) + '/*SAFE/manifest.safe') 146 | print (files) 147 | out_file.write(str(files)+'\n') 148 | 149 | if not os.path.exists(splitmasterfolder): 150 | os.makedirs(splitmasterfolder) 151 | IWlist=[ 'IW1','IW2','IW3'] 152 | for IW in IWlist: 153 | outputname=acdatefolder+'_'+IW+'.dim' 154 | print('Splitting master with AOI intersecting '+IW) 155 | if len(files) == 1 : 156 | graphxml=os.path.join(GRAPH,'topsar_master_split_applyorbit.xml') 157 | # Read in the file 158 | print( 'FILE(s) : '+files[0]) 159 | with open(graphxml, 'r') as file : 160 | filedata = file.read() 161 | # Replace the target string 162 | filedata = filedata.replace('INPUTFILE', files[0]) 163 | filedata = filedata.replace('IWs',IW) 164 | filedata = filedata.replace('POLARISATION',POLARISATION) 165 | filedata = filedata.replace('POLYGON',polygon) 166 | filedata = filedata.replace('OUTPUTFILE',os.path.join(splitmasterfolder,outputname)) 167 | # # Write the file out again 168 | with open(graph2run, 'w') as file: 169 | file.write(filedata) 170 | if len(files) == 2 : 171 | graphxml=os.path.join(GRAPH,'topsar_master_assemble_split_applyorbit.xml') 172 | with open(graphxml, 'r') as file : 173 | filedata = file.read() 174 | # Replace the target string 175 | filedata = filedata.replace('INPUTFILE1', files[0]) 176 | filedata = filedata.replace('INPUTFILE2', files[1]) 177 | filedata = filedata.replace('IWs',IW) 178 | filedata = filedata.replace('POLARISATION',POLARISATION) 179 | filedata = filedata.replace('POLYGON',polygon) 180 | filedata = filedata.replace('OUTPUTFILE',os.path.join(splitmasterfolder,outputname)) 181 | 182 | # Write the file out again 183 | with open(graph2run, 'w') as file: 184 | file.write(filedata) 185 | 186 | args = [ GPT, graph2run, '-c', CACHE, '-q', CPU] 187 | print (args) 188 | out_file.write(str(args)+'\n') 189 | # launching the process 190 | timeStarted = time.time() 191 | process = Popen(args, bufsize=1, stdout=PIPE, stderr=STDOUT) 192 | r = b"" 193 | for line in process.stdout: 194 | r += line 195 | print(line.decode('utf-8')) 196 | process.wait() 197 | timeDelta = time.time() - timeStarted # Get execution time. 198 | print('['+IW+'] Finished process in '+str(timeDelta)+' seconds.') 199 | out_file.write('['+str(IW)+'] Finished process in '+str(timeDelta)+' seconds.\n') 200 | if process.returncode != 0 : 201 | message='Master image does not intersect '+str(polygon)+' in subswath '+IW 202 | err_file.write(message) 203 | else: 204 | message='Split master '+str(files)+' in subswath '+IW+' successfully completed.\n' 205 | print( message) 206 | out_file.write(message) 207 | print( bar_message) 208 | out_file.write(bar_message) 209 | out_file.close() 210 | 211 | # Updating project.conf file with new Master splitted 212 | #with open(inputfile, 'r') as file : 213 | # filedata = file.read() 214 | # Replace the target string 215 | #filedata = filedata.replace('MASTER=','MASTER='+splitmasterfolder+'/'+outputname) 216 | # Write the file out again 217 | #with open(inputfile, 'w') as file: 218 | # file.write(filedata) 219 | -------------------------------------------------------------------------------- /bin/topsar_step_4_plotting_all.py: -------------------------------------------------------------------------------- 1 | import os 2 | from pathlib import Path 3 | import sys 4 | import glob 5 | from subprocess import PIPE, Popen, STDOUT 6 | import shlex 7 | import time 8 | import shutil 9 | 10 | import configparser 11 | import warnings 12 | import argparse 13 | 14 | sys.stdout.flush() 15 | warnings.filterwarnings('ignore') 16 | 17 | parser = argparse.ArgumentParser(description='This script create PNG files from each data with the options split/coreg/ifg') 18 | parser.add_argument("--ProjFile","-F", type=str) 19 | parser.add_argument("--Mode","-M", type=str) 20 | 21 | args = parser.parse_args() 22 | 23 | def usage(): 24 | message='####################################################\n' 25 | message=message+'Usage: python '+sys.argv[0]+' -F [project.conf] -M [mode] \n' 26 | message=message+' project.conf file\n' 27 | message=message+' mode : split/coreg/ifg\n' 28 | message=message+'All parameters mandatory' 29 | return message 30 | 31 | if not args.ProjFile: 32 | print("No Input File detected") 33 | print(usage()) 34 | sys.exit(-1) 35 | else: 36 | configfile = args.ProjFile 37 | if not args.Mode: 38 | print('No Mode selected') 39 | print(usage()) 40 | sys.exit(-1) 41 | else: 42 | mode=args.Mode 43 | 44 | 45 | bar_message='\n#####################################################################\n' 46 | # Setting LD_LIBRARY_PATH for SNAP 47 | os.environ["LD_LIBRARY_PATH"] = "." 48 | 49 | # Getting configuration variables from inputfile 50 | config = configparser.ConfigParser() 51 | config.read(configfile) 52 | 53 | PROJECT=config['PROJECT_DEFINITION'].get('PROJECTFOLDER') 54 | GRAPH=config['PROJECT_DEFINITION'].get('GRAPHSFOLDER') 55 | 56 | OVERWRITE=config['PROC_OPTIONS'].get('OVERWRITE') 57 | SMARTHDD=config['PROC_OPTIONS'].get('SMARTHDD') 58 | 59 | POLARISATION=config['PROC_PARAMETERS'].get('POLARISATION') 60 | MASTER=config['PROC_PARAMETERS'].get('MASTERFOLDER') 61 | 62 | CACHE=config['COMPUTING_RESOURCES'].get('CACHE') 63 | CPU=config['COMPUTING_RESOURCES'].get('CPU') 64 | 65 | ################################################################### 66 | ## GETTING PATH to gpt executable 67 | SNAPFOLDER=config['SNAP_GPT'].get('SNAP_INSTALLATION_FOLDER') 68 | GPT=os.path.join(SNAPFOLDER,'bin','gpt') 69 | PCONVERT=os.path.join(SNAPFOLDER,'bin','pconvert') 70 | if os.name == 'nt': 71 | GPT=os.path.join(SNAPFOLDER,'bin','gpt.exe') 72 | PCONVERT=os.path.join(SNAPFOLDER,'bin','pconvert.exe') 73 | sys.exit() 74 | 75 | SNAPHIDDEN=config['SNAP_GPT'].get('SNAP_HOME_DIR') 76 | PALETTES=os.path.join(SNAPHIDDEN,'auxdata','color_palettes') 77 | 78 | ################################################################################## 79 | # Checking GPT 80 | if not os.path.exists(GPT) or not os.path.exists(PCONVERT): 81 | errormessage="GPT or PCONVERT executable not found in "+os.path.dirname(GPT)+".Processing aborted" 82 | print(errormessage) 83 | sys.exit(errormessage) 84 | 85 | ###################################################################################### 86 | ## Plotting Slaves amplitude and Interferometric phase ## 87 | ###################################################################################### 88 | # Initializing set-up 89 | masterfolder=PROJECT+'/MasterSplit' 90 | secondariesplittedfolder=PROJECT+'/split' 91 | coregfolder=PROJECT+'/coreg' 92 | ifgfolder=PROJECT+'/ifg' 93 | graphfolder=PROJECT+'/graphs' 94 | logfolder=PROJECT+'/logs' 95 | plotfolder=PROJECT+'/plot/'+mode 96 | if not os.path.exists(graphfolder): 97 | os.makedirs(graphfolder) 98 | if not os.path.exists(logfolder): 99 | os.makedirs(logfolder) 100 | if not os.path.exists(plotfolder): 101 | os.makedirs(plotfolder) 102 | 103 | outlog=logfolder+'/plot_stdout.log' 104 | if mode == 'split': 105 | graphxml=GRAPH+'/topsar_plot_amplitude_deburst.xml' 106 | searchfolder=secondariesplittedfolder 107 | ibandname='i_*'+POLARISATION 108 | qbandname='q_*'+POLARISATION 109 | elif mode == 'coreg': 110 | graphxml=GRAPH+'/plot_amplitude.xml' 111 | searchfolder=coregfolder 112 | ibandname='i_*'+POLARISATION+'_slv1' 113 | qbandname='q_*'+POLARISATION+'_slv1' 114 | elif mode == 'ifg': 115 | graphxml=GRAPH+'/plot_phase.xml' 116 | searchfolder=ifgfolder 117 | ibandname='i_ifg_*'+POLARISATION 118 | qbandname='q_ifg_*'+POLARISATION 119 | graph2run=graphfolder+'/plot2run_'+mode+'.xml' 120 | 121 | out_file = open(outlog, 'a') 122 | err_file=out_file 123 | 124 | print (bar_message) 125 | out_file.write(bar_message) 126 | message='## Plotting secondaries amplitude and Interferometric phase started:\n' 127 | print( message) 128 | out_file.write(message) 129 | print (bar_message) 130 | out_file.write(bar_message) 131 | 132 | 133 | for masters in sorted(glob.glob(masterfolder+'/*dim')): 134 | 135 | IW=masters[-7:-4] 136 | print(IW) 137 | k=0 138 | for dimfile in sorted(glob.iglob(searchfolder + '/*'+IW+'.dim')): 139 | print (dimfile) 140 | k=k+1 141 | head, tail = os.path.split(os.path.join(searchfolder, dimfile)) 142 | message='['+str(k)+'] Processing file :'+tail+'\n' 143 | print( message) 144 | out_file.write(message) 145 | tailm=os.path.basename(masters) 146 | #outputname=tailm[17:25]+'_'+tail[0:8]+'_'+IW 147 | #outputname=outputname+'_'+mode 148 | outputname=tail[:-4]+'_'+mode 149 | print(outputname) 150 | #outputname2=outputname+'_coreg' 151 | #outputname3=outputname+'_phase' 152 | print(searchfolder+'/'+tail[:-3]+'data/'+ibandname+'*img') 153 | iband=glob.glob(searchfolder+'/'+tail[:-3]+'data/'+ibandname+'*.img') 154 | iband=os.path.basename(iband[0]) 155 | iband=iband.split('.')[0] 156 | qband=glob.glob(searchfolder+'/'+tail[:-3]+'data/'+qbandname+'*.img') 157 | qband=os.path.basename(qband[0]) 158 | qband=qband.split('.')[0] 159 | print(iband) 160 | print(qband) 161 | with open(graphxml, 'r') as file : 162 | filedata = file.read() 163 | # Replace the target string 164 | filedata = filedata.replace('INPUTFILE', dimfile) 165 | filedata = filedata.replace('OUTPUTFOLDER',plotfolder) 166 | filedata = filedata.replace('OUTPUTNAME',outputname) 167 | filedata = filedata.replace('IBAND',iband) 168 | filedata = filedata.replace('QBAND',qband) 169 | # Write the file out again 170 | with open(graph2run, 'w') as file: 171 | file.write(filedata) 172 | args = [ GPT, graph2run, '-c', CACHE, '-q', CPU] 173 | # Check if exists 174 | print(plotfolder+'/'+outputname+'.dim') 175 | if not os.path.exists(str(plotfolder+'/'+outputname+'.png')) and OVERWRITE=='N': 176 | # Launch the processing 177 | print('Creating file :'+outputname+'.dim') 178 | timeStarted = time.time() 179 | process = Popen(args, bufsize=1, stdout=PIPE, stderr=PIPE) 180 | r = b"" 181 | for line in process.stdout: 182 | r += line 183 | print(str(line)) 184 | process.wait() 185 | timeDelta = time.time() - timeStarted # Get execution time. 186 | print('['+str(k)+'] Finished process in '+str(timeDelta)+' seconds.') 187 | out_file.write('['+str(k)+'] Finished process in '+str(timeDelta)+' seconds.\n') 188 | if process.returncode != 0 : 189 | print('Returncode :'+str(process.returncode)) 190 | message='Error creating png of splitted secondaries '+str(dimfile) 191 | err_file.write(message+'\n') 192 | else: 193 | message='Aux file of '+str(tail)+' successfully generated.\n' 194 | print (message) 195 | out_file.write(message) 196 | ## CONVERTING TO PNG 197 | color=PALETTES+'/spectrum_cycle.cpd' 198 | #color=PALETTES+'/spectrum_large.cpd' 199 | #color=PALETTES+'/JET.cpd' 200 | inputfile=plotfolder+'/'+outputname+'.dim' 201 | # For amplitude info 202 | if mode == 'ifg': 203 | args=[PCONVERT,'-b','1','-c',color,'-f','png','-o',plotfolder,inputfile] 204 | else : 205 | args=[PCONVERT,'-b','1','-f','png','-o',plotfolder,inputfile] 206 | print(args) 207 | # Launch the processing 208 | timeStarted = time.time() 209 | process = Popen(args, bufsize=1, stdout=PIPE, stderr=PIPE) 210 | r = b"" 211 | for line in process.stdout: 212 | r += line 213 | print(str(line)) 214 | process.wait() 215 | timeDelta = time.time() - timeStarted # Get execution time. 216 | print('['+str(k)+'] Finished process in '+str(timeDelta)+' seconds.') 217 | out_file.write('['+str(k)+'] Finished process in '+str(timeDelta)+' seconds.\n') 218 | if process.returncode != 0 : 219 | print('Returncode :'+str(process.returncode)) 220 | message='Error creating png of splitted secondaries '+str(dimfile) 221 | err_file.write(message+'\n') 222 | else: 223 | message='PNG of '+str(tail)+' successfully completed.\n' 224 | print('Removing tmp file :'+inputfile) 225 | os.remove(inputfile) 226 | shutil.rmtree(inputfile[:-3]+'data') 227 | print (message) 228 | out_file.write(message) 229 | else: 230 | message="File :"+outputname+" already exists. Processing skipped" 231 | print(message) 232 | print(bar_message) 233 | out_file.write(message) 234 | out_file.write(bar_message) 235 | out_file.close() 236 | -------------------------------------------------------------------------------- /bin/topsar_step_2_splitting_secondaries.py: -------------------------------------------------------------------------------- 1 | ### Python script to use SNAP as InSAR processor compatible with StaMPS PSI processing 2 | # Author Jose Manuel Delgado Blasco 3 | # Date: 21/06/2018 4 | # Updated: 01/06/2023 5 | # Version: 2.0 6 | 7 | # Step 0 : preparing secondary images in folder structure 8 | # Step 1 : Master TOPSAR Splitting (Assembling) and Apply Orbit 9 | # Step 2 : TOPSAR Splitting (Assembling) and Apply Orbit of Secondary Images 10 | # Step 3 : Coregistration and Interferogram generation 11 | # Step 4 : StaMPS export 12 | # Step 5 : Plotting secondaries and interferometric phase 13 | 14 | # Added option for CACHE and CPU specification by user 15 | # Planned support for DEM selection and ORBIT type selection 16 | 17 | 18 | import configparser 19 | import argparse 20 | import warnings 21 | import io 22 | import os 23 | from pathlib import Path 24 | import sys 25 | import glob 26 | from subprocess import PIPE, Popen,STDOUT 27 | import shlex 28 | import time 29 | 30 | import geopandas as gpd 31 | 32 | sys.stdout.flush() 33 | inputfile = sys.argv[1] 34 | warnings.filterwarnings('ignore') 35 | 36 | parser = argparse.ArgumentParser(description='This script splits the master Sentinel-1 image') 37 | parser.add_argument("--ProjFile","-F", type=str) 38 | 39 | args = parser.parse_args() 40 | if not args.ProjFile: 41 | print("No Input File detected") 42 | sys.exit(-1) 43 | else: 44 | configfile = args.ProjFile 45 | 46 | bar_message='\n#####################################################################\n' 47 | # Setting LD_LIBRARY_PATH for SNAP 48 | #os.environ["LD_LIBRARY_PATH"] = os.getcwd() 49 | os.environ["LD_LIBRARY_PATH"] ="." 50 | # Getting configuration variables from inputfile 51 | config = configparser.ConfigParser() 52 | config.read(configfile) 53 | 54 | PROJECT=config['PROJECT_DEFINITION'].get('PROJECTFOLDER') 55 | GRAPH=config['PROJECT_DEFINITION'].get('GRAPHSFOLDER') 56 | 57 | OVERWRITE=config['PROC_OPTIONS'].get('OVERWRITE') 58 | SMARTHDD=config['PROC_OPTIONS'].get('SMARTHDD') 59 | 60 | POLARISATION=config['PROC_PARAMETERS'].get('POLARISATION') 61 | MASTERFOLDER=config['PROC_PARAMETERS'].get('MASTERFOLDER') 62 | 63 | CACHE=config['COMPUTING_RESOURCES'].get('CACHE') 64 | CPU=config['COMPUTING_RESOURCES'].get('CPU') 65 | 66 | ######################################################### 67 | ## GETTING AOI DEFINITION 68 | aoi_mode=config['AOI_DEFINITION'].get('AOI_MODE') 69 | print(aoi_mode) 70 | if aoi_mode == 'WKT': 71 | polygon=config['AOI_DEFINITION'].get('WKT') 72 | elif aoi_mode == 'BBOX': 73 | LONMIN=config['AOI_DEFINITION'].get('LONMIN') 74 | LATMIN=config['AOI_DEFINITION'].get('LATMIN') 75 | LONMAX=config['AOI_DEFINITION'].get('LONMAX') 76 | LATMAX=config['AOI_DEFINITION'].get('LATMAX') 77 | polygon='POLYGON (('+LONMIN+' '+LATMIN+','+LONMAX+' '+LATMIN+','+LONMAX+' '+LATMAX+','+LONMIN+' '+LATMAX+','+LONMIN+' '+LATMIN+'))' 78 | elif aoi_mode == 'SHP' or aoi_mode == 'GeoJSON' or aoi_mode == 'KML': 79 | AOIFile=config['AOI_DEFINITION'].get('AOI_FILE') 80 | if aoi_mode != 'KML': 81 | gdf=gpd.read_file(AOIFile) 82 | else: 83 | import fiona 84 | fiona.drvsupport.supported_drivers['KML'] = 'rw' 85 | gdf = gpd.read_file(AOIFile, driver='KML') 86 | #polygon=str(gdf['geometry'].wkt) 87 | 88 | from shapely import wkt 89 | #polygon = wkt.dumps(gdf['geometry'][0]) 90 | polygon = str(gdf.envelope[0]) 91 | # print(polygon) 92 | else: 93 | print('Wrong AOI_MODE parameter! Please revise the configuration file') 94 | sys.exit() 95 | 96 | print( polygon) 97 | 98 | ################################################################### 99 | ## GETTING PATH to gpt executable 100 | SNAPFOLDER=config['SNAP_GPT'].get('SNAP_INSTALLATION_FOLDER') 101 | GPT=os.path.join(SNAPFOLDER,'bin','gpt') 102 | if os.name == 'nt': 103 | GPT=os.path.join(SNAPFOLDER,'bin','gpt.exe') 104 | 105 | ############################################################################# 106 | ### TOPSAR Splitting (Assembling) and Apply Orbit section #### 107 | ############################################################################ 108 | # Checking GPT 109 | if not os.path.exists(str(GPT)): 110 | errormessage="GPT executable not found in "+GPT+".Processing aborted" 111 | print(errormessage) 112 | sys.exit(errormessage) 113 | # Initializing set-up 114 | secondariesfolder=os.path.join(PROJECT,'secondaries') 115 | masterfolder=os.path.join(PROJECT,'MasterSplit') 116 | splitfolder=os.path.join(PROJECT,'split') 117 | logfolder=os.path.join(PROJECT,'logs') 118 | graphfolder=os.path.join(PROJECT,'graphs') 119 | 120 | if not os.path.exists(splitfolder): 121 | os.makedirs(splitfolder) 122 | if not os.path.exists(logfolder): 123 | os.makedirs(logfolder) 124 | if not os.path.exists(graphfolder): 125 | os.makedirs(graphfolder) 126 | ######################################## 127 | # Define execute command 128 | def execute(command): 129 | process = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) 130 | 131 | # Poll process for new output until finished 132 | while True: 133 | nextline = process.stdout.readline() 134 | if nextline == '' :#and process.poll() is not None: 135 | break 136 | sys.stdout.write(nextline.decode('utf-8')) 137 | sys.stdout.flush() 138 | 139 | output = process.communicate()[0] 140 | exitCode = process.returncode 141 | 142 | # if (exitCode == 0): 143 | # return output 144 | # else: 145 | # raise ProcessException(command, exitCode, output) 146 | ######################################## 147 | graph2run=os.path.join(graphfolder,'splitgraph2run.xml') 148 | outlog=os.path.join(logfolder,'splitsecondaries.log') 149 | out_file = open(outlog, 'a') 150 | err_file=out_file 151 | 152 | print( bar_message) 153 | out_file.write(bar_message) 154 | message='## TOPSAR Splitting and Apply Orbit\n' 155 | print( message) 156 | out_file.write(message) 157 | print( bar_message) 158 | out_file.write(bar_message) 159 | k=0 160 | for acdatefolder in sorted(os.listdir(secondariesfolder)): 161 | k=k+1 162 | print( '['+str(k)+'] Folder: '+acdatefolder) 163 | out_file.write('['+str(k)+'] Folder: '+acdatefolder+'\n') 164 | print( os.path.join(secondariesfolder, acdatefolder)) 165 | out_file.write(str(os.path.join(secondariesfolder, acdatefolder))+'\n') 166 | # files = glob.glob(os.path.join(secondariesfolder, acdatefolder) + '/*.safe') 167 | files = glob.glob(os.path.join(secondariesfolder, acdatefolder) + '/*.zip') 168 | if len(files)==0: 169 | files = glob.glob(os.path.join(secondariesfolder, acdatefolder) + '/*SAFE/manifest.safe') 170 | print( files) 171 | out_file.write(str(files)+'\n') 172 | head, tail = os.path.split(os.path.join(str(files))) 173 | #splitsecondariesfolder=splitfolder+'/'+tail[17:25] 174 | #splitsecondariesfolder=splitfolder+'/'+acdatefolder[0:8] 175 | splitsecondariesfolder=splitfolder 176 | if not os.path.exists(splitsecondariesfolder): 177 | os.makedirs(splitsecondariesfolder) 178 | for masters in sorted(glob.glob(masterfolder+'/*dim')): 179 | IW=masters[-7:-4] 180 | print(IW) 181 | outputname=tail[17:25]+'_'+IW+'.dim' 182 | outputname=acdatefolder+'_'+IW+'.dim' 183 | print('Outname:'+outputname) 184 | if not os.path.exists(str(splitsecondariesfolder+'/'+outputname)) and OVERWRITE=='N': 185 | if len(files) == 1 : 186 | graphxml=os.path.join(GRAPH,'topsar_secondaries_split_applyorbit.xml') 187 | # Read in the file 188 | print( 'FILE(s) : '+files[0]) 189 | with open(graphxml, 'r') as file : 190 | filedata = file.read() 191 | # Replace the target string 192 | filedata = filedata.replace('INPUTFILE', files[0]) 193 | filedata = filedata.replace('IWs',IW) 194 | filedata = filedata.replace('POLARISATION',POLARISATION) 195 | filedata = filedata.replace('POLYGON',polygon) 196 | filedata = filedata.replace('OUTPUTFILE',splitsecondariesfolder+'/'+outputname) 197 | # # Write the file out again 198 | with open(graph2run, 'w') as file: 199 | file.write(filedata) 200 | if len(files) > 1 : 201 | graphxml=os.path.join(GRAPH,'topsar_secondaries_assemble_split_applyorbit.xml') 202 | with open(graphxml, 'r') as file : 203 | filedata = file.read() 204 | # Replace the target string 205 | filedata = filedata.replace('INPUTFILE1', files[0]) 206 | filedata = filedata.replace('INPUTFILE2', files[1]) 207 | filedata = filedata.replace('IWs',IW) 208 | filedata = filedata.replace('POLARISATION',POLARISATION) 209 | filedata = filedata.replace('POLYGON',polygon) 210 | filedata = filedata.replace('OUTPUTFILE',splitsecondariesfolder+'/'+outputname) 211 | # Write the file out again 212 | with open(graph2run, 'w') as file: 213 | file.write(filedata) 214 | 215 | args = [ GPT, graph2run, '-c', CACHE, '-q', CPU] 216 | # args = GPT+' '+graph2run+' -c '+CACHE+' -q '+CPU 217 | print( args) 218 | out_file.write(str(args)+'\n') 219 | # launching the process 220 | ###process = subprocess.Popen(args, stdout=subprocess.PIPE,stderr=subprocess.STDOUT) 221 | timeStarted = time.time() 222 | process = Popen(args, bufsize=1, stdout=PIPE, stderr=STDOUT) 223 | r = b"" 224 | for line in process.stdout: 225 | r += line 226 | print(line.decode('utf-8')) 227 | process.wait() 228 | ## execute(args) 229 | ###stdout = process.communicate()[0] 230 | ###print ('SNAP STDOUT:{}'.format(stdout)) 231 | timeDelta = time.time() - timeStarted # Get execution time. 232 | print(('['+str(k)+'] Finished process in '+str(timeDelta)+' seconds.')) 233 | out_file.write('['+str(k)+'] Finished process in '+str(timeDelta)+' seconds.\n') 234 | if process.returncode != 0 : 235 | message='Error splitting secondaries '+str(files) 236 | err_file.write(message) 237 | else: 238 | message='Split secondaries '+str(files)+' successfully completed.\n' 239 | print( message) 240 | out_file.write(message) 241 | print( bar_message) 242 | else: 243 | message="File :"+outputname+" already exists. Processing skipped" 244 | print(message) 245 | print(bar_message) 246 | out_file.write(message) 247 | out_file.write(bar_message) 248 | out_file.write(bar_message) 249 | out_file.close() 250 | -------------------------------------------------------------------------------- /bin/topsar_step_5_stamps_export_multiIW.py: -------------------------------------------------------------------------------- 1 | ### Python script to use SNAP as InSAR processor compatible with StaMPS PSI processing 2 | # Author Jose Manuel Delgado Blasco 3 | # Date: 21/06/2018 4 | # Updated: 01/04/2020 5 | # Version: 2.0 6 | 7 | # Step 0 : preparing secondaries in folder structure 8 | # Step 1 : Master TOPSAR Splitting (Assembling) and Apply Orbit 9 | # Step 2 : TOPSAR Splitting (Assembling) and Apply Orbit 10 | # Step 3 : Coregistration and Interferogram generation 11 | # Step 4 (optional): Plotting splitted and coregistered secondaries and interferometric phase 12 | # Step 5 : StaMPS export 13 | 14 | # Added in version 1.0 15 | ## Option for CACHE and CPU specification by user 16 | # Added in version 2.0 17 | ## Automatic Master splitting 18 | ## Slave TOPSAR Splitting based on BBOX coordinates (LATMIN, LONMIN, LATMAX, LONMAX) 19 | ## Multi-Subswath support (merging prior StaMPS export) 20 | ## Convertion from shapefile to BBOX coordinates 21 | ## Option for disk space optimisation 22 | ## Option for overwrite or skip existing files 23 | ## Plotting scripts (secondaries and interferograms) 24 | # Planned support for DEM selection and ORBIT type selection 25 | 26 | import configparser 27 | import argparse 28 | import warnings 29 | import io 30 | import os 31 | from pathlib import Path 32 | import sys 33 | import glob 34 | from subprocess import PIPE, Popen, STDOUT 35 | import shlex 36 | import time 37 | import numpy as np 38 | import geopandas as gpd 39 | import shutil 40 | 41 | sys.stdout.flush() 42 | inputfile = sys.argv[1] 43 | warnings.filterwarnings('ignore') 44 | 45 | parser = argparse.ArgumentParser(description='This script splits the master Sentinel-1 image') 46 | parser.add_argument("--ProjFile","-F", type=str) 47 | 48 | args = parser.parse_args() 49 | if not args.ProjFile: 50 | print("No Input File detected") 51 | sys.exit(-1) 52 | else: 53 | configfile = args.ProjFile 54 | 55 | 56 | bar_message='\n#####################################################################\n' 57 | # Setting LD_LIBRARY_PATH for SNAP 58 | #os.environ["LD_LIBRARY_PATH"] = os.getcwd() 59 | os.environ["LD_LIBRARY_PATH"] = "." 60 | 61 | 62 | config = configparser.ConfigParser() 63 | config.read(configfile) 64 | 65 | PROJECT=config['PROJECT_DEFINITION'].get('PROJECTFOLDER') 66 | GRAPH=config['PROJECT_DEFINITION'].get('GRAPHSFOLDER') 67 | 68 | OVERWRITE=config['PROC_OPTIONS'].get('OVERWRITE') 69 | SMARTHDD=config['PROC_OPTIONS'].get('SMARTHDD') 70 | 71 | MASTER=config['PROC_PARAMETERS'].get('MASTERFOLDER') 72 | extDEM=config['PROC_PARAMETERS'].get('EXTDEM') 73 | 74 | CACHE=config['COMPUTING_RESOURCES'].get('CACHE') 75 | CPU=config['COMPUTING_RESOURCES'].get('CPU') 76 | 77 | ######################################################### 78 | ## GETTING AOI DEFINITION 79 | aoi_mode=config['AOI_DEFINITION'].get('AOI_MODE') 80 | print(aoi_mode) 81 | if aoi_mode == 'WKT': 82 | polygon=config['AOI_DEFINITION'].get('WKT') 83 | elif aoi_mode == 'BBOX': 84 | LONMIN=config['AOI_DEFINITION'].get('LONMIN') 85 | LATMIN=config['AOI_DEFINITION'].get('LATMIN') 86 | LONMAX=config['AOI_DEFINITION'].get('LONMAX') 87 | LATMAX=config['AOI_DEFINITION'].get('LATMAX') 88 | polygon='POLYGON (('+LONMIN+' '+LATMIN+','+LONMAX+' '+LATMIN+','+LONMAX+' '+LATMAX+','+LONMIN+' '+LATMAX+','+LONMIN+' '+LATMIN+'))' 89 | elif aoi_mode == 'SHP' or aoi_mode == 'GeoJSON' or aoi_mode == 'KML': 90 | AOIFile=config['AOI_DEFINITION'].get('AOI_FILE') 91 | if aoi_mode != 'KML': 92 | gdf=gpd.read_file(AOIFile) 93 | else: 94 | import fiona 95 | fiona.drvsupport.supported_drivers['KML'] = 'rw' 96 | gdf = gpd.read_file(AOIFile, driver='KML') 97 | #polygon=str(gdf['geometry'].wkt) 98 | from shapely import wkt 99 | polygon = wkt.dumps(gdf['geometry'][0]) 100 | polygon = str(gdf.envelope[0]) 101 | # print(polygon) 102 | else: 103 | print('Wrong AOI_MODE parameter! Please revise the configuration file') 104 | sys.exit() 105 | 106 | print( polygon) 107 | 108 | ################################################################### 109 | ## GETTING PATH to gpt executable 110 | SNAPFOLDER=config['SNAP_GPT'].get('SNAP_INSTALLATION_FOLDER') 111 | GPT=os.path.join(SNAPFOLDER,'bin','gpt') 112 | if os.name == 'nt': 113 | GPT=os.path.join(SNAPFOLDER,'bin','gpt.exe') 114 | 115 | ################################################################################### 116 | # Checking GPT 117 | if not os.path.exists(GPT): 118 | errormessage="GPT executable not found in "+GPT+".Processing aborted" 119 | print(errormessage) 120 | sys.exit(errormessage) 121 | 122 | 123 | ################################################################################### 124 | ##### StaMPS PSI export ################## 125 | ################################################################################### 126 | masterfolder=os.path.join(PROJECT,'MasterSplit') 127 | coregfolder=os.path.join(PROJECT,'coreg') 128 | ifgfolder=os.path.join(PROJECT,'ifg') 129 | graphfolder=os.path.join(PROJECT,'graphs') 130 | logfolder=os.path.join(PROJECT,'logs') 131 | masters=sorted(glob.glob(masterfolder+'/*dim')) 132 | MASTER=masters[0] 133 | head, tail = os.path.split(MASTER) 134 | #outputexportfolder=PROJECT+'/INSAR_'+tail[17:25] 135 | outputexportfolder=os.path.join(PROJECT,'INSAR_'+tail[0:8]) 136 | 137 | if not os.path.exists(outputexportfolder): 138 | os.makedirs(outputexportfolder) 139 | if not os.path.exists(logfolder): 140 | os.makedirs(logfolder) 141 | 142 | outlog=os.path.join(logfolder,'export_proc_stdout.log') 143 | out_file = open(outlog, 'a') 144 | err_file=out_file 145 | graph2run=os.path.join(graphfolder,'export2run.xml') 146 | print( bar_message) 147 | out_file.write(bar_message) 148 | message='## StaMPS PSI export started:\n' 149 | print( message) 150 | out_file.write(message) 151 | print( bar_message) 152 | out_file.write(bar_message) 153 | k=0 154 | 155 | masters=sorted(glob.glob(masterfolder+'/*dim')) 156 | if len(masters)==1: 157 | graphxml=os.path.join(GRAPH,'topsar_export.xml') 158 | else: 159 | graphxml=os.path.join(GRAPH,'topsar_export_mergeIW_subset.xml') 160 | if extDEM!='': 161 | graphxml=graphxml[:-4]+'_extDEM.xml' 162 | #IW=masters[-7:-4] 163 | #print(IW) 164 | pairs=[] 165 | for dimfile in sorted(glob.iglob(coregfolder + '/*.dim')): 166 | head, tail = os.path.split(os.path.join(coregfolder, dimfile)) 167 | k=k+1 168 | pair=tail[0:17] 169 | # print(pair) 170 | pairs.append(pair) 171 | pairs=np.unique(pairs) 172 | #print(pairs) 173 | 174 | dimfile=None 175 | ifgdim=None 176 | k=0 177 | for pair in pairs: 178 | k=k+1 179 | dimfiles=sorted(glob.iglob(coregfolder+'/'+pair+'*.dim')) 180 | message='['+str(k)+'] Exporting pair: master-secondary pair '+pair+'\n' 181 | ifgdims = sorted(glob.iglob(ifgfolder+'/'+pair+'*.dim')) 182 | print(dimfiles) 183 | print( ifgdims) 184 | #dimfile.append(dimfiles) 185 | #ifgdim.append(ifgdims) 186 | for m in range(0,len(dimfiles)): 187 | if m==0: 188 | dimfile=dimfiles[m] 189 | ifgdim=ifgdims[m] 190 | else: 191 | dimfile=dimfile+','+dimfiles[m] 192 | ifgdim=ifgdim+','+ifgdims[m] 193 | print('Coreg and ifg files:') 194 | print(dimfile) 195 | print(ifgdim) 196 | print( message) 197 | out_file.write(message) 198 | with open(graphxml, 'r') as file : 199 | filedata = file.read() 200 | # Replace the target string 201 | filedata = filedata.replace('COREGFILE',dimfile) 202 | filedata = filedata.replace('IFGFILE', str(ifgdim)) 203 | filedata = filedata.replace('OUTPUTFOLDER',outputexportfolder) 204 | filedata = filedata.replace('EXTERNALDEM',extDEM) 205 | filedata = filedata.replace('POLYGON',polygon) 206 | # Write the file out again 207 | with open(graph2run, 'w') as file: 208 | file.write(filedata) 209 | args = [ GPT, graph2run, '-c', CACHE, '-q', CPU] 210 | print( args) 211 | # Launching process 212 | timeStarted = time.time() 213 | ### process = subprocess.Popen(args, stdout=subprocess.PIPE,stderr=subprocess.STDOUT) 214 | ### process.wait() 215 | # timeStarted = time.time() 216 | ### stdout = process.communicate()[0] 217 | ### print( 'SNAP STDOUT:{}'.format(stdout).decode('utf-8')) 218 | process = Popen(args, bufsize=1, stdout=PIPE, stderr=STDOUT) 219 | r = b"" 220 | for line in process.stdout: 221 | r += line 222 | print(line.decode('utf-8')) 223 | process.wait() 224 | timeDelta = time.time() - timeStarted 225 | # Get execution time. 226 | print('['+str(k)+'] Finished process in '+str(timeDelta)+' seconds.') 227 | out_file.write('['+str(k)+'] Finished process in '+str(timeDelta)+' seconds.\n') 228 | if process.returncode != 0 : 229 | message='Error exporting '+str(os.path.basename(ifgdim))+'\n' 230 | err_file.write(message) 231 | else: 232 | message='Stamps export of '+str(os.path.basename(ifgdim))+' successfully completed.\n' 233 | if k>1 and SMARTHDD =="Y": 234 | for p in range(0,len(ifgdims)): 235 | os.remove(ifgdims[p]) 236 | os.remove(dimfiles[p]) 237 | print('removing :'+ifgdims[p][:-3]+'data') 238 | shutil.rmtree(ifgdims[p][:-3]+'data') 239 | shutil.rmtree(dimfiles[p][:-3]+'data') 240 | current_dir=os.getcwd() 241 | targetdim=glob.glob(current_dir+'/target.dim') 242 | if len(targetdim)>0: 243 | os.remove(targetdim[0]) 244 | targetdata = os.path.join(current_dir, 'target.data') 245 | if len(targetdata)>0 and os.path.isdir(targetdata): 246 | shutil.rmtree(targetdata) 247 | print( message) 248 | out_file.write(message) 249 | print( bar_message) 250 | out_file.write(bar_message) 251 | out_file.close() 252 | err_file.close() 253 | 254 | # Check and remove of extra files target.dim and target.data generated by SNAP (SNAP's bug) 255 | current_dir=os.getcwd() 256 | targetdim=glob.glob(current_dir+'/target.dim') 257 | if len(targetdim)>0: 258 | os.remove(targetdim[0]) 259 | 260 | targetdata = os.path.join(current_dir, 'target.data') 261 | if os.path.exists(targetdata) and os.path.isdir(targetdata): 262 | shutil.rmtree(targetdata) 263 | -------------------------------------------------------------------------------- /bin/topsar_step_3_coreg_ifg_topsar_smart.py: -------------------------------------------------------------------------------- 1 | ### Python script to use SNAP as InSAR processor compatible with StaMPS PSI processing 2 | # Author Jose Manuel Delgado Blasco 3 | # Date: 21/06/2018 4 | # Updated: 01/06/2023 5 | # Version: 2.0 6 | 7 | # Step 0 : preparing secondary images in folder structure 8 | # Step 1 : Master TOPSAR Splitting (Assembling) and Apply Orbit 9 | # Step 2 : TOPSAR Splitting (Assembling) and Apply Orbit of Secondary Images 10 | # Step 3 : Coregistration and Interferogram generation 11 | # Step 4 : StaMPS export 12 | # Step 5 : Plotting secondaries and interferometric phase 13 | 14 | # Added option for CACHE and CPU specification by user 15 | # Planned support for DEM selection and ORBIT type selection 16 | import configparser 17 | import argparse 18 | import warnings 19 | import io 20 | import os 21 | from pathlib import Path 22 | import sys 23 | import glob 24 | from subprocess import PIPE, Popen 25 | import shlex 26 | import time 27 | 28 | import geopandas as gpd 29 | 30 | sys.stdout.flush() 31 | inputfile = sys.argv[1] 32 | warnings.filterwarnings('ignore') 33 | 34 | parser = argparse.ArgumentParser(description='This script executes the coregistration and ifg computation of Sentinel-1 image pairs') 35 | parser.add_argument("--ProjFile","-F", type=str) 36 | 37 | args = parser.parse_args() 38 | if not args.ProjFile: 39 | print("No Input File detected") 40 | sys.exit(-1) 41 | else: 42 | configfile = args.ProjFile 43 | 44 | bar_message='\n#####################################################################\n' 45 | # Setting LD_LIBRARY_PATH for SNAP 46 | os.environ["LD_LIBRARY_PATH"] = "." 47 | # Getting configuration variables from inputfile 48 | config = configparser.ConfigParser() 49 | config.read(configfile) 50 | 51 | PROJECT=config['PROJECT_DEFINITION'].get('PROJECTFOLDER') 52 | GRAPH=config['PROJECT_DEFINITION'].get('GRAPHSFOLDER') 53 | 54 | OVERWRITE=config['PROC_OPTIONS'].get('OVERWRITE') 55 | SMARTHDD=config['PROC_OPTIONS'].get('SMARTHDD') 56 | 57 | MASTERFOLDER=config['PROC_PARAMETERS'].get('MASTERFOLDER') 58 | extDEM=config['PROC_PARAMETERS'].get('EXTDEM') 59 | 60 | CACHE=config['COMPUTING_RESOURCES'].get('CACHE') 61 | CPU=config['COMPUTING_RESOURCES'].get('CPU') 62 | 63 | ######################################################### 64 | ## GETTING AOI DEFINITION 65 | aoi_mode=config['AOI_DEFINITION'].get('AOI_MODE') 66 | print(aoi_mode) 67 | if aoi_mode == 'WKT': 68 | polygon=config['AOI_DEFINITION'].get('WKT') 69 | elif aoi_mode == 'BBOX': 70 | LONMIN=config['AOI_DEFINITION'].get('LONMIN') 71 | LATMIN=config['AOI_DEFINITION'].get('LATMIN') 72 | LONMAX=config['AOI_DEFINITION'].get('LONMAX') 73 | LATMAX=config['AOI_DEFINITION'].get('LATMAX') 74 | polygon='POLYGON (('+LONMIN+' '+LATMIN+','+LONMAX+' '+LATMIN+','+LONMAX+' '+LATMAX+','+LONMIN+' '+LATMAX+','+LONMIN+' '+LATMIN+'))' 75 | 76 | elif aoi_mode == 'SHP' or aoi_mode == 'GeoJSON' or aoi_mode == 'KML': 77 | AOIFile=config['AOI_DEFINITION'].get('AOI_FILE') 78 | if aoi_mode != 'KML': 79 | gdf=gpd.read_file(AOIFile) 80 | else: 81 | import fiona 82 | fiona.drvsupport.supported_drivers['KML'] = 'rw' 83 | gdf = gpd.read_file(AOIFile, driver='KML') 84 | 85 | #polygon=str(gdf['geometry'].wkt) 86 | from shapely import wkt 87 | polygon = wkt.dumps(gdf['geometry'][0]) 88 | polygon = str(gdf.envelope[0]) 89 | # print(polygon) 90 | 91 | else: 92 | print('Wrong AOI_MODE parameter! Please revise the configuration file') 93 | sys.exit() 94 | 95 | print(polygon) 96 | 97 | ################################################################### 98 | ## GETTING PATH to gpt executable 99 | SNAPFOLDER=config['SNAP_GPT'].get('SNAP_INSTALLATION_FOLDER') 100 | GPT=os.path.join(SNAPFOLDER,'bin','gpt') 101 | if os.name == 'nt': 102 | GPT=os.path.join(SNAPFOLDER,'bin','gpt.exe') 103 | 104 | ###################################################################################### 105 | ## TOPSAR Coregistration and Interferogram formation ## 106 | ###################################################################################### 107 | # Checking GPT 108 | if not os.path.exists(GPT): 109 | errormessage="GPT executable not found in "+GPT+".Processing aborted" 110 | print(errormessage) 111 | # sys.exit(errormessage) 112 | # Initializing set-up 113 | masterfolder=os.path.join(PROJECT,'MasterSplit') 114 | secondariesplittedfolder=os.path.join(PROJECT,'split') 115 | outputcoregfolder=os.path.join(PROJECT,'coreg') 116 | outputifgfolder=os.path.join(PROJECT,'ifg') 117 | graphfolder=os.path.join(PROJECT,'graphs') 118 | logfolder=os.path.join(PROJECT,'logs') 119 | 120 | if not os.path.exists(outputcoregfolder): 121 | os.makedirs(outputcoregfolder) 122 | if not os.path.exists(outputifgfolder): 123 | os.makedirs(outputifgfolder) 124 | if not os.path.exists(graphfolder): 125 | os.makedirs(graphfolder) 126 | if not os.path.exists(logfolder): 127 | os.makedirs(logfolder) 128 | 129 | outlog=os.path.join(logfolder,'coreg_ifg_proc_stdout.log') 130 | graph2run=os.path.join(graphfolder,'coreg_ifg2run.xml') 131 | 132 | out_file = open(outlog, 'a') 133 | err_file=out_file 134 | 135 | def get_nbursts(inputfile): 136 | print('Checking N bursts in file '+inputfile) 137 | file1=open(inputfile,'r') 138 | Lines=file1.readlines() 139 | 140 | count=0 141 | for line in Lines: 142 | count +=1 143 | if "burstList" in line: 144 | print("Line {} :{}".format(count,line.strip())) 145 | nbursts=Lines[count].split('>')[1].split('<')[0] 146 | print(nbursts) 147 | return int(nbursts) 148 | return 1 149 | 150 | 151 | print (bar_message) 152 | out_file.write(bar_message) 153 | message='## Coregistration and Interferogram computation started:\n' 154 | print( message) 155 | out_file.write(message) 156 | print (bar_message) 157 | out_file.write(bar_message) 158 | 159 | for masters in sorted(glob.glob(masterfolder+'/*dim')): 160 | k=0 161 | nmasters=len(sorted(glob.glob(masterfolder+'/*dim'))) 162 | print('N masters:'+str(nmasters)) 163 | graphxml=os.path.join(GRAPH,'topsar_coreg_ifg_computation') 164 | if nmasters==1: 165 | graphxml=graphxml+'_subset' 166 | 167 | if get_nbursts(os.path.join(masterfolder,masters)) ==1: 168 | graphxml=graphxml+'_noESD' 169 | 170 | if extDEM=="": 171 | graphxml=graphxml+'.xml' 172 | else: 173 | graphxml=graphxml+'_extDEM.xml' 174 | 175 | print('graph :'+graphxml) 176 | IW=masters[-7:-4] 177 | print(masters) 178 | print(IW) 179 | for dimfile in sorted(glob.iglob(secondariesplittedfolder + '/*'+IW+'.dim')): 180 | print (dimfile) 181 | k=k+1 182 | head, tail = os.path.split(os.path.join(secondariesplittedfolder, dimfile)) 183 | message='['+str(k)+'] Processing secondaries file :'+tail+'\n' 184 | print( message) 185 | out_file.write(message) 186 | head , tailm = os.path.split(os.path.join(masters)) 187 | outputname=tailm[17:25]+'_'+tail[0:8]+'_'+IW 188 | outputname=tailm[0:8]+'_'+tail[0:8]+'_'+IW 189 | print(outputname) 190 | with open(graphxml, 'r') as file : 191 | filedata = file.read() 192 | # Replace the target string 193 | filedata = filedata.replace('MASTER',masters) 194 | filedata = filedata.replace('SECONDARY', dimfile) 195 | filedata = filedata.replace('EXTERNALDEM',extDEM) 196 | filedata = filedata.replace('OUTPUTCOREGFOLDER',outputcoregfolder) 197 | filedata = filedata.replace('OUTPUTIFGFOLDER', outputifgfolder) 198 | filedata = filedata.replace('OUTPUTFILE',outputname) 199 | filedata = filedata.replace('POLYGON',polygon) 200 | # Write the file out again 201 | with open(graph2run, 'w') as file: 202 | file.write(filedata) 203 | args = [ GPT, graph2run, '-c', CACHE, '-q', CPU] 204 | # Check if exists 205 | if not os.path.exists(str(outputcoregfolder+'/'+outputname+'.dim')) and OVERWRITE=='N': 206 | # Launch the processing 207 | timeStarted = time.time() 208 | process = Popen(args, bufsize=1, stdout=PIPE, stderr=PIPE) 209 | r = b"" 210 | for line in process.stdout: 211 | r += line 212 | print(line.decode('utf-8')) 213 | process.wait() 214 | timeDelta = time.time() - timeStarted # Get execution time. 215 | print('['+str(k)+'] Finished process in '+str(timeDelta)+' seconds.') 216 | out_file.write('['+str(k)+'] Finished process in '+str(timeDelta)+' seconds.\n') 217 | if process.returncode != 0 : 218 | print('Returncode :'+str(process.returncode)) 219 | message='Error computing with coregistration and interferogram generation of splitted secondaries '+str(dimfile) 220 | err_file.write(message+'\n') 221 | else: 222 | message='Coregistration and Interferogram computation for data '+str(tail)+' successfully completed.\n' 223 | print (message) 224 | out_file.write(message) 225 | #print (bar_message) 226 | ## Cleaning up duplicated bands and info 227 | if SMARTHDD == 'Y' : 228 | print('Optimising disk data volume option activated!') 229 | srccoreg=sorted(glob.glob(outputcoregfolder+'/*.data/'))[0] 230 | ifile=glob.glob(srccoreg+'/i*mst*img')[0] 231 | qfile=glob.glob(srccoreg+'/q*mst*img')[0] 232 | srcifg=sorted(glob.glob(outputifgfolder+'/*.data'))[0] 233 | dem1=glob.glob(srcifg+'/elevation.img')#[0] 234 | if len(dem1)>0: 235 | dem=dem1[0] 236 | lat1=glob.glob(srcifg+'/orthorectifiedLat.img')#[0] 237 | if len(lat1)>0: 238 | lat=lat1[0] 239 | lon1=glob.glob(srcifg+'/orthorectifiedLon.img')#[0] 240 | if len(lon1)>0: 241 | lon=lon1[0] 242 | #else: 243 | # print('Optimising disk data volume option deactivated!') 244 | if SMARTHDD == 'Y' and k>1: 245 | #print('Removing duplicated files:') 246 | # Removing master coregistered from stacks (from second onwards) 247 | files = glob.glob(outputcoregfolder+'/'+outputname+'.data/*mst*.img') 248 | if len(files)>0: 249 | os.remove(files[0]) 250 | # print(files[0]) 251 | # print('linking :'+ifile+' '+files[0]) 252 | os.symlink(ifile,files[0]) 253 | if len(files)==2: 254 | os.remove(files[1]) 255 | # print(files[1]) 256 | # print('linking :'+qfile+' '+files[1]) 257 | os.symlink(qfile,files[1]) 258 | # Removing orthorectified Lat/Long bands (all equal for each stack) 259 | files = glob.glob(outputifgfolder+'/'+outputname+'.data/orthorectified*.img') 260 | if len(files)>0: 261 | os.remove(files[0]) 262 | # print(files[0]) 263 | # print('linking :'+lat+' '+files[0]) 264 | os.symlink(lat,files[0]) 265 | if len(files)==2: 266 | os.remove(files[1]) 267 | # print(files[1]) 268 | # print('linking :'+lon+' '+files[1]) 269 | os.symlink(lon,files[1]) 270 | # Removing elevation band (all equal for each stack) 271 | files = glob.glob(outputifgfolder+'/'+outputname+'.data/elevation.img') 272 | if len(files)>0: 273 | os.remove(files[0]) 274 | # print(files[0]) 275 | # print('linking :'+dem+' '+files[0]) 276 | os.symlink(dem,files[0]) 277 | print(bar_message) 278 | else: 279 | message="File :"+outputname+" already exists. Processing skipped" 280 | print(message) 281 | print(bar_message) 282 | out_file.write(message) 283 | out_file.write(bar_message) 284 | out_file.close() 285 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # SNAP2StaMPS v2 DOI [![License: CC BY-NC-SA 4.0](https://img.shields.io/badge/License-CC%20BY--NC--SA%204.0-lightgrey.svg)](https://creativecommons.org/licenses/by-nc-sa/4.0/) [![Github All Releases](https://img.shields.io/github/downloads/mdelgadoblasco/snap2stamps/total.svg)](https://GitHub.com/mdelgadoblasco/snap2stamps/releases/) 2 | SNAP2StaMPS v2: Using SNAP as InSAR processor for StaMPS 3 | 4 | **(Updated on 2023/09/20)** 5 | 6 | This repository and the included scripts call routines of the ESA SentiNel Application Platform (SNAP) to perform TOPSAR interferometric processing producing compatible inputs for the open-source StaMPS package. 7 | 8 | ***The provided scripts with this SNAP to StaMPS package are not part of the SNAP software. The provided scripts are open-source contributions and should not be mistaken for official Applications within SNAP. The scripts are provided to you "as is" with no warranties of corrections.*** 9 | 10 | This new provided package (SNAP2StaMPSv2) evolves from the initial SNAP2StaMPS package and was presented at FRINGE WORKSHOP 2023 in Leeds, September 2023 with zenodo doi [10.5281/zenodo.8362628](https://doi.org/10.5281/zenodo.8362628). 11 | 12 | Authors: 13 | - José Manuel Delgado Blasco, "Microgeodesia Jaén" Research Group (MJaén), Jaén, Spain 14 | - Jonas Ziemer, Department for Earth Observation, Friedrich Schiller University Jena (FSU), Germany 15 | - Michael Foumelis, Aristotle University of Thessaloniki (AUTh), Greece 16 | - Clémence Dubois, Department for Earth Observation, Friedrich Schiller University Jena (FSU), Germany 17 | 18 | ## Description 19 | SNAP2StaMPS version 2 tries to collect feedback and it has been built to minimize issues from the user side due to package installation, or other dependencies due to software versioning, etc. Further, the new version supports the preprocessing of high-resolution TerraSAR-/TanDEM-X Stripmap data including and enhancing the TSX2Stamps package for the preparation of StaMPS PSI processing. TSX2Stamps uses a similar workflow as applied to Sentinel-1 TOPSAR data in the previous version of SNAP2StaMPS. The TSX2Stamps package is also freely available as standalone package for download on GitHub (https://github.com/jziemer1996/TSX2StaMPS). Please find below the general workflow of SNAP2StaMPS v2. For further information, please check the information given below or have a look at the tutorial provided within this repository. 20 | 21 | ![Snap2stamps_v2_workflow](https://github.com/mdelgadoblasco/snap2stamps/assets/56928368/04612220-b580-44ac-a2b3-e51d2c364bc4) 22 | 23 | ## Important notes: 24 | ### SNAP2StaMPS execution 25 | This new version provides 2 different ways of using the package: 26 | 1. Standard Python execution from the command line (similar to version 1) 27 | 2. Advanced execution using dockerised software (under testing) 28 | 29 | ### Before starting: 30 | The scripts are hardcoded to use SRTM 1Sec HGT DEM which are automatically downloaded from the ESA STEP repository. 31 | > **Note**: 32 | > Coregistration with DEM (Backgeocoding or DEM-Assisted-Coreg) or TopoPhaseRemoval might hang up if the SAR data footprint falls in areas where no valid SRTM1 tile exists. This might happen in areas near the Coastline. To avoid possible issues try to ensure SAR data footprints fall inside valid SRTM1 Sec tiles. 33 | 34 | > **Note**: 35 | > Please note that the TSX2Stamps package was developed using an External DEM with a high spatial resolution (5m). For the processing of TSX stripmap data, we highly recommend using an External DEM with a higher spatial resolution than provided by SRTM to ensure the best possible quality for the ingestion in StaMPS. 36 | 37 | > **Warning**: 38 | > If the user wants to use its own External DEM, please ensure it is in geotiff format with no data values as 0.0 and preprocessed using egm84 ellipsoid. Otherwise, ensure to adapt the parameters in the xml graphs accordingly. 39 | 40 | ### New project configuration files (for Topsar and Stripmap processing) 41 | Due to the integration of Stripmap data, the new SNAP2StaMPS package consists of two separate branches (SNAP2StaMPSv1 and TSX2Stamps) with two different config files (project_topsar.conf and project_stripmap.conf). Please spend some time understanding the (new) options available in the configuration files. 42 | 43 | The new project configuration files include TAGS for newer options such as: 44 | - Sentinel-1 data download from Alaska Satellite Facilities* using the asf_search package 45 | - Support new AOI definition methods, BBOX, WKT, SHP, KML or GeoJSON 46 | - Sentinel-1 master selection methods: AUTO / MANUAL / FIRST / LAST 47 | - and more ... 48 | 49 | Since TSX/TDX data is not freely available, the download and auto-master selection is only available for Sentinel-1 data. Consequently, the configuration file of stripmap data comes without these parameters and is slightly different. 50 | 51 | >**Note**: 52 | >The Sentinel-1 data download requires the provisioning of valid and registered credentials from ASF in the configuration file section **[SEARCH_PARAMS]** in **ASF_USER** and **ASF_PASS**. If needed, click [here](https://asf.alaska.edu/) to register at the Alaska Satellite Facilities website 53 | 54 | See below the detailed information that can be defined within the project_topsar.conf file: 55 | 56 | ```bash 57 | ################### TOPSAR CONFIGURATION FILE ############################# 58 | ########################################################################### 59 | [PROJECT_DEFINITION] 60 | PROJECTFOLDER = /media/Storage/SNAP2stamps_test_small/ 61 | GRAPHSFOLDER = /home/jmdb/SNAPping/SNAP2stamps_v2/tmp/SNAP2stamps/graphs 62 | ########################################################################### 63 | [PROC_OPTIONS] 64 | # Y / N OPTIONS 65 | OVERWRITE = N 66 | SMARTHDD = Y 67 | PLOTTING = Y 68 | ########################################################################### 69 | [PROC_PARAMETERS] 70 | # SENSOR : S1 71 | SENSOR = S1 72 | POLARISATION = VV 73 | MASTER = /media/Storage/SNAP2stamps_test_small/Master/ 74 | # MASTER SELECTION : AUTO / FIRST / LAST / MANUAL 75 | MASTERSEL = MANUAL 76 | EXTDEM = 77 | ########################################################################### 78 | [AOI_DEFINITION] 79 | #AOI_MODE OPTIONS BBOX / SHP / KML / GeoJSON 80 | AOI_MODE = SHP 81 | LONMIN = 54.2 82 | LATMIN = 24.36 83 | LONMAX = 55.66 84 | LATMAX = 25.42 85 | AOI_FILE = /media/Storage/SNAP2stamps_test/aoi/aoi.shp 86 | ############################################################################ 87 | [SEARCH_PARAMS] 88 | # autoDownload : Y / N 89 | autoDownload = N 90 | TRACK = 117 91 | # beamMode : SLC / GRD 92 | beamMode = SLC 93 | # START/ STOP in YYYY-MM-DD 94 | START = 2020-02-01 95 | END = 2020-04-16 96 | # SAT : S1 / S1A / S1B 97 | SAT= S1A 98 | ASF_USER = 99 | ASF_PASS = 100 | # Number of Parallel Downloads (NPD) 101 | [SEARCH_PDOWNLOADS] 102 | NPD = 4 103 | ############################################################################ 104 | [SNAP_GPT] 105 | SNAP_INSTALLATION_FOLDER = /home/jmdb/anaconda/envs/SNAP2stamps/SNAP/ 106 | SNAP_HOME_DIR = /home/jmdb/anaconda/envs/SNAP2stamps/.SNAP 107 | ############################################################################ 108 | [COMPUTING_RESOURCES] 109 | CPU = 8 110 | CACHE = 16G 111 | ############################################################################ 112 | ``` 113 | # Using the SNAP2StaMPS package 114 | ## 1. Standard Execution: Python package 115 | ### 1.1. Dependencies / Requirements 116 | 1. Git 117 | 2. conda: SNAP2StaMPS v2 includes the definition of a yml file which includes a customized ESA SNAP (v.9.0) conda package. 118 | 3. SNAP 9.0 dependencies to be installed in OS libfftw3, libgfortran (example for Linux OS). 119 | >**Note**: Using the environment yml provided there is no need for additional installation of ESA SNAP 120 | 121 | ### 1.2. Installation 122 | ```bash 123 | sudo apt update 124 | sudo apt install git libfftw3 libgfortran #(Ubuntu 20.04) 125 | sudo apt install fftw-dev gfortran #(Ubuntu 22.04) 126 | git clone https://github.com/mdelgadoblasco/snap2stamps.git 127 | conda env create -f snap2stamps_environment.yml 128 | ``` 129 | 130 | ### 1.3. Usage 131 | 132 | The user may choose to run: 133 | 1. The auto_run.py script that automates the full workflow with the command below. 134 | ```bash 135 | python auto_run.py -F project_topsar.conf # for Sentinel-1 TOPSAR data 136 | python auto_run.py -F project_stripmap.conf # for TSX Stripmap data 137 | ``` 138 | By running the above script the workflow may include the Sentinel-1 data download and the master selection according to the definition of the project_topsar.conf file. For TSX, these options are not available and the data download has to be done manually. 139 | 140 | 2. The step-by-step approach for 141 | - Sentinel-1 TOPSAR processing: 142 | ```bash 143 | python asf_s1_downloader.py -F project.conf #[optional] 144 | python topsar_step_0_secondaries_prep.py -F project.conf 145 | python topsar_automaster.py -F project.conf -M AUTO #[optional] 146 | python topsar_step_1_splitting_master_multi_IW.py -F project.conf 147 | python topsar_step_2_splitting_secondaries.py -F project.conf 148 | python topsar_step_3_coreg_ifg_topsar_smart.py -F project.conf 149 | python topsar_step_4_plotting_all.py -F project.conf #[optional] 150 | python topsar_step_5_stamps_export_multiIW.py -F project.conf 151 | ``` 152 | - TerraSAR-X Stripmap processing: 153 | ```bash 154 | python stripmap_step_0a_unpack_sar_scenes.py -F project.conf 155 | python stripmap_step_0b_secondaries_prep.py -F project.conf 156 | python stripmap_step_1_subset_sar.py -F project.conf 157 | python stripmap_step_1b_masterselection.py -F project.conf 158 | python stripmap_step_2_coreg_sar.py -F project.conf 159 | python stripmap_step_3_ifg_sar.py -F project.conf 160 | python stripmap_step_4_plotting_all.py -F project.conf #[optional] 161 | python stripmap_step_5_stamps_export.py -F project.conf 162 | ``` 163 | A new feature of this release is the plotting of the images resulting from subsetting, coregistration, and interferogram generation. To generate the plots run the following code by specifying the desired mode: 164 | - for splitted or subsetted files: 165 | ```bash 166 | python auto_run.py -F project_topsar.conf -M split 167 | ``` 168 | - for coregistered files: 169 | ```bash 170 | python auto_run.py -F project_topsar.conf -M coreg 171 | ``` 172 | - for the interferograms: 173 | ```bash 174 | python auto_run.py -F project_topsar.conf -M ifg 175 | ``` 176 | The same applies to stripmap data by using the project_stripmap.conf file instead of topsar. 177 | 178 | # v2.0 Release features 179 | - SNAP2StaMPS update to **Python 3.11 and SNAP v9.0** 180 | - Autorun script to **automate full processing** steps 181 | - Sentinel-1 **master selection** script for automation 182 | - Master splitting in the command line 183 | - Support to Sentinel-1 Multi Subswath 184 | - Support to single burst AOI 185 | - Support to TerraSAR-X Stripmap with DEM assisted coregistration 186 | - Support to BBOX, WKT, SHP, KML, GeoJSON formats for AOI definition 187 | - Support to External DEM usage (DEM preparation routines not included) 188 | - Plotting coregistered slcs and ifgs 189 | - Smart options for disk optimization 190 | 191 | # Contributing 192 | - José Manuel Delgado Blasco (Research Group Microgeodesia Jaén, Jaén, Spain) 193 | - Jonas Ziemer (University of Jena, Germany) 194 | - Michael Foumelis (University of Thessaloniki, Greece) 195 | - Clémence Dubois (University of Jena, Germany) 196 | 197 | The team is open to new contributions, so don't be shy and share them with the community. 198 | 199 | # Acknowledgments 200 | We want to acknowledge: 201 | - Fabio Cian 202 | - Andreas Braun 203 | - Andre Theron 204 | ## Questions and inquiries 205 | For questions and inquiries, we want to promote the usage of the [ESA STEP Forum](https://forum.step.esa.int/) that has been used very much until now. 206 | 207 | # License 208 | ![image](https://github.com/mdelgadoblasco/snap2stamps_v2/assets/20595425/e36c71bc-8c10-4bd8-ae92-c6b4dac077c7) 209 | **CC BY-NC-SA**: [Creative Commons Attribution-NonCommercial-ShareAlike](https://creativecommons.org/licenses/by-nc-sa/4.0) 210 | 211 | This license lets others remix, adapt, and build upon your work non-commercially, as long as they credit you and license their new creations under the identical terms. 212 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | # Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International (CC BY-NC-SA 4.0) ![image](https://github.com/mdelgadoblasco/snap2stamps_v2/assets/20595425/053408fe-9c65-4441-a8e6-2c09489cca36) 2 | 3 | Creative Commons Corporation (“Creative Commons”) is not a law firm and does not provide legal services or legal advice. Distribution of Creative Commons public licenses does not create a lawyer-client or other relationship. Creative Commons makes its licenses and related information available on an “as-is” basis. Creative Commons gives no warranties regarding its licenses, any material licensed under their terms and conditions, or any related information. Creative Commons disclaims all liability for damages resulting from their use to the fullest extent possible. 4 | 5 | **Using Creative Commons Public Licenses** 6 | 7 | Creative Commons public licenses provide a standard set of terms and conditions that creators and other rights holders may use to share original works of authorship and other material subject to copyright and certain other rights specified in the public license below. The following considerations are for informational purposes only, are not exhaustive, and do not form part of our licenses. 8 | 9 | * __Considerations for licensors:__ Our public licenses are intended for use by those authorized to give the public permission to use material in ways otherwise restricted by copyright and certain other rights. Our licenses are irrevocable. Licensors should read and understand the terms and conditions of the license they choose before applying it. Licensors should also secure all rights necessary before applying our licenses so that the public can reuse the material as expected. Licensors should clearly mark any material not subject to the license. This includes other CC-licensed material, or material used under an exception or limitation to copyright. [More considerations for licensors](http://wiki.creativecommons.org/Considerations_for_licensors_and_licensees#Considerations_for_licensors). 10 | 11 | * __Considerations for the public:__ By using one of our public licenses, a licensor grants the public permission to use the licensed material under specified terms and conditions. If the licensor’s permission is not necessary for any reason–for example, because of any applicable exception or limitation to copyright–then that use is not regulated by the license. Our licenses grant only permissions under copyright and certain other rights that a licensor has authority to grant. Use of the licensed material may still be restricted for other reasons, including because others have copyright or other rights in the material. A licensor may make special requests, such as asking that all changes be marked or described. Although not required by our licenses, you are encouraged to respect those requests where reasonable. [More considerations for the public](http://wiki.creativecommons.org/Considerations_for_licensors_and_licensees#Considerations_for_licensees). 12 | 13 | ## Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International Public License 14 | 15 | By exercising the Licensed Rights (defined below), You accept and agree to be bound by the terms and conditions of this Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International Public License ("Public License"). To the extent this Public License may be interpreted as a contract, You are granted the Licensed Rights in consideration of Your acceptance of these terms and conditions, and the Licensor grants You such rights in consideration of benefits the Licensor receives from making the Licensed Material available under these terms and conditions. 16 | 17 | ### Section 1 – Definitions. 18 | 19 | a. __Adapted Material__ means material subject to Copyright and Similar Rights that is derived from or based upon the Licensed Material and in which the Licensed Material is translated, altered, arranged, transformed, or otherwise modified in a manner requiring permission under the Copyright and Similar Rights held by the Licensor. For purposes of this Public License, where the Licensed Material is a musical work, performance, or sound recording, Adapted Material is always produced where the Licensed Material is synched in timed relation with a moving image. 20 | 21 | b. __Adapter's License__ means the license You apply to Your Copyright and Similar Rights in Your contributions to Adapted Material in accordance with the terms and conditions of this Public License. 22 | 23 | c. __BY-NC-SA Compatible License__ means a license listed at [creativecommons.org/compatiblelicenses](http://creativecommons.org/compatiblelicenses), approved by Creative Commons as essentially the equivalent of this Public License. 24 | 25 | d. __Copyright and Similar Rights__ means copyright and/or similar rights closely related to copyright including, without limitation, performance, broadcast, sound recording, and Sui Generis Database Rights, without regard to how the rights are labeled or categorized. For purposes of this Public License, the rights specified in Section 2(b)(1)-(2) are not Copyright and Similar Rights. 26 | 27 | e. __Effective Technological Measures__ means those measures that, in the absence of proper authority, may not be circumvented under laws fulfilling obligations under Article 11 of the WIPO Copyright Treaty adopted on December 20, 1996, and/or similar international agreements. 28 | 29 | f. __Exceptions and Limitations__ means fair use, fair dealing, and/or any other exception or limitation to Copyright and Similar Rights that applies to Your use of the Licensed Material. 30 | 31 | g. __License Elements__ means the license attributes listed in the name of a Creative Commons Public License. The License Elements of this Public License are Attribution, NonCommercial, and ShareAlike. 32 | 33 | h. __Licensed Material__ means the artistic or literary work, database, or other material to which the Licensor applied this Public License. 34 | 35 | i. __Licensed Rights__ means the rights granted to You subject to the terms and conditions of this Public License, which are limited to all Copyright and Similar Rights that apply to Your use of the Licensed Material and that the Licensor has authority to license. 36 | 37 | j. __Licensor__ means the individual(s) or entity(ies) granting rights under this Public License. 38 | 39 | k. __NonCommercial__ means not primarily intended for or directed towards commercial advantage or monetary compensation. For purposes of this Public License, the exchange of the Licensed Material for other material subject to Copyright and Similar Rights by digital file-sharing or similar means is NonCommercial provided there is no payment of monetary compensation in connection with the exchange. 40 | 41 | l. __Share__ means to provide material to the public by any means or process that requires permission under the Licensed Rights, such as reproduction, public display, public performance, distribution, dissemination, communication, or importation, and to make material available to the public including in ways that members of the public may access the material from a place and at a time individually chosen by them. 42 | 43 | m. __Sui Generis Database Rights__ means rights other than copyright resulting from Directive 96/9/EC of the European Parliament and of the Council of 11 March 1996 on the legal protection of databases, as amended and/or succeeded, as well as other essentially equivalent rights anywhere in the world. 44 | 45 | n. __You__ means the individual or entity exercising the Licensed Rights under this Public License. __Your__ has a corresponding meaning. 46 | 47 | ### Section 2 – Scope. 48 | 49 | a. ___License grant.___ 50 | 51 | 1. Subject to the terms and conditions of this Public License, the Licensor hereby grants You a worldwide, royalty-free, non-sublicensable, non-exclusive, irrevocable license to exercise the Licensed Rights in the Licensed Material to: 52 | 53 | A. reproduce and Share the Licensed Material, in whole or in part, for NonCommercial purposes only; and 54 | 55 | B. produce, reproduce, and Share Adapted Material for NonCommercial purposes only. 56 | 57 | 2. __Exceptions and Limitations.__ For the avoidance of doubt, where Exceptions and Limitations apply to Your use, this Public License does not apply, and You do not need to comply with its terms and conditions. 58 | 59 | 3. __Term.__ The term of this Public License is specified in Section 6(a). 60 | 61 | 4. __Media and formats; technical modifications allowed.__ The Licensor authorizes You to exercise the Licensed Rights in all media and formats whether now known or hereafter created, and to make technical modifications necessary to do so. The Licensor waives and/or agrees not to assert any right or authority to forbid You from making technical modifications necessary to exercise the Licensed Rights, including technical modifications necessary to circumvent Effective Technological Measures. For purposes of this Public License, simply making modifications authorized by this Section 2(a)(4) never produces Adapted Material. 62 | 63 | 5. __Downstream recipients.__ 64 | 65 | A. __Offer from the Licensor – Licensed Material.__ Every recipient of the Licensed Material automatically receives an offer from the Licensor to exercise the Licensed Rights under the terms and conditions of this Public License. 66 | 67 | B. __Additional offer from the Licensor – Adapted Material.__ Every recipient of Adapted Material from You automatically receives an offer from the Licensor to exercise the Licensed Rights in the Adapted Material under the conditions of the Adapter’s License You apply. 68 | 69 | C. __No downstream restrictions.__ You may not offer or impose any additional or different terms or conditions on, or apply any Effective Technological Measures to, the Licensed Material if doing so restricts exercise of the Licensed Rights by any recipient of the Licensed Material. 70 | 71 | 6. __No endorsement.__ Nothing in this Public License constitutes or may be construed as permission to assert or imply that You are, or that Your use of the Licensed Material is, connected with, or sponsored, endorsed, or granted official status by, the Licensor or others designated to receive attribution as provided in Section 3(a)(1)(A)(i). 72 | 73 | b. ___Other rights.___ 74 | 75 | 1. Moral rights, such as the right of integrity, are not licensed under this Public License, nor are publicity, privacy, and/or other similar personality rights; however, to the extent possible, the Licensor waives and/or agrees not to assert any such rights held by the Licensor to the limited extent necessary to allow You to exercise the Licensed Rights, but not otherwise. 76 | 77 | 2. Patent and trademark rights are not licensed under this Public License. 78 | 79 | 3. To the extent possible, the Licensor waives any right to collect royalties from You for the exercise of the Licensed Rights, whether directly or through a collecting society under any voluntary or waivable statutory or compulsory licensing scheme. In all other cases the Licensor expressly reserves any right to collect such royalties, including when the Licensed Material is used other than for NonCommercial purposes. 80 | 81 | ### Section 3 – License Conditions. 82 | 83 | Your exercise of the Licensed Rights is expressly made subject to the following conditions. 84 | 85 | a. ___Attribution.___ 86 | 87 | 1. If You Share the Licensed Material (including in modified form), You must: 88 | 89 | A. retain the following if it is supplied by the Licensor with the Licensed Material: 90 | 91 | i. identification of the creator(s) of the Licensed Material and any others designated to receive attribution, in any reasonable manner requested by the Licensor (including by pseudonym if designated); 92 | 93 | ii. a copyright notice; 94 | 95 | iii. a notice that refers to this Public License; 96 | 97 | iv. a notice that refers to the disclaimer of warranties; 98 | 99 | v. a URI or hyperlink to the Licensed Material to the extent reasonably practicable; 100 | 101 | B. indicate if You modified the Licensed Material and retain an indication of any previous modifications; and 102 | 103 | C. indicate the Licensed Material is licensed under this Public License, and include the text of, or the URI or hyperlink to, this Public License. 104 | 105 | 2. You may satisfy the conditions in Section 3(a)(1) in any reasonable manner based on the medium, means, and context in which You Share the Licensed Material. For example, it may be reasonable to satisfy the conditions by providing a URI or hyperlink to a resource that includes the required information. 106 | 107 | 3. If requested by the Licensor, You must remove any of the information required by Section 3(a)(1)(A) to the extent reasonably practicable. 108 | 109 | b. ___ShareAlike.___ 110 | 111 | In addition to the conditions in Section 3(a), if You Share Adapted Material You produce, the following conditions also apply. 112 | 113 | 1. The Adapter’s License You apply must be a Creative Commons license with the same License Elements, this version or later, or a BY-NC-SA Compatible License. 114 | 115 | 2. You must include the text of, or the URI or hyperlink to, the Adapter's License You apply. You may satisfy this condition in any reasonable manner based on the medium, means, and context in which You Share Adapted Material. 116 | 117 | 3. You may not offer or impose any additional or different terms or conditions on, or apply any Effective Technological Measures to, Adapted Material that restrict exercise of the rights granted under the Adapter's License You apply. 118 | 119 | ### Section 4 – Sui Generis Database Rights. 120 | 121 | Where the Licensed Rights include Sui Generis Database Rights that apply to Your use of the Licensed Material: 122 | 123 | a. for the avoidance of doubt, Section 2(a)(1) grants You the right to extract, reuse, reproduce, and Share all or a substantial portion of the contents of the database for NonCommercial purposes only; 124 | 125 | b. if You include all or a substantial portion of the database contents in a database in which You have Sui Generis Database Rights, then the database in which You have Sui Generis Database Rights (but not its individual contents) is Adapted Material, including for purposes of Section 3(b); and 126 | 127 | c. You must comply with the conditions in Section 3(a) if You Share all or a substantial portion of the contents of the database. 128 | 129 | For the avoidance of doubt, this Section 4 supplements and does not replace Your obligations under this Public License where the Licensed Rights include other Copyright and Similar Rights. 130 | 131 | ### Section 5 – Disclaimer of Warranties and Limitation of Liability. 132 | 133 | a. __Unless otherwise separately undertaken by the Licensor, to the extent possible, the Licensor offers the Licensed Material as-is and as-available, and makes no representations or warranties of any kind concerning the Licensed Material, whether express, implied, statutory, or other. This includes, without limitation, warranties of title, merchantability, fitness for a particular purpose, non-infringement, absence of latent or other defects, accuracy, or the presence or absence of errors, whether or not known or discoverable. Where disclaimers of warranties are not allowed in full or in part, this disclaimer may not apply to You.__ 134 | 135 | b. __To the extent possible, in no event will the Licensor be liable to You on any legal theory (including, without limitation, negligence) or otherwise for any direct, special, indirect, incidental, consequential, punitive, exemplary, or other losses, costs, expenses, or damages arising out of this Public License or use of the Licensed Material, even if the Licensor has been advised of the possibility of such losses, costs, expenses, or damages. Where a limitation of liability is not allowed in full or in part, this limitation may not apply to You.__ 136 | 137 | c. The disclaimer of warranties and limitation of liability provided above shall be interpreted in a manner that, to the extent possible, most closely approximates an absolute disclaimer and waiver of all liability. 138 | 139 | ### Section 6 – Term and Termination. 140 | 141 | a. This Public License applies for the term of the Copyright and Similar Rights licensed here. However, if You fail to comply with this Public License, then Your rights under this Public License terminate automatically. 142 | 143 | b. Where Your right to use the Licensed Material has terminated under Section 6(a), it reinstates: 144 | 145 | 1. automatically as of the date the violation is cured, provided it is cured within 30 days of Your discovery of the violation; or 146 | 147 | 2. upon express reinstatement by the Licensor. 148 | 149 | For the avoidance of doubt, this Section 6(b) does not affect any right the Licensor may have to seek remedies for Your violations of this Public License. 150 | 151 | c. For the avoidance of doubt, the Licensor may also offer the Licensed Material under separate terms or conditions or stop distributing the Licensed Material at any time; however, doing so will not terminate this Public License. 152 | 153 | d. Sections 1, 5, 6, 7, and 8 survive termination of this Public License. 154 | 155 | ### Section 7 – Other Terms and Conditions. 156 | 157 | a. The Licensor shall not be bound by any additional or different terms or conditions communicated by You unless expressly agreed. 158 | 159 | b. Any arrangements, understandings, or agreements regarding the Licensed Material not stated herein are separate from and independent of the terms and conditions of this Public License. 160 | 161 | ### Section 8 – Interpretation. 162 | 163 | a. For the avoidance of doubt, this Public License does not, and shall not be interpreted to, reduce, limit, restrict, or impose conditions on any use of the Licensed Material that could lawfully be made without permission under this Public License. 164 | 165 | b. To the extent possible, if any provision of this Public License is deemed unenforceable, it shall be automatically reformed to the minimum extent necessary to make it enforceable. If the provision cannot be reformed, it shall be severed from this Public License without affecting the enforceability of the remaining terms and conditions. 166 | 167 | c. No term or condition of this Public License will be waived and no failure to comply consented to unless expressly agreed to by the Licensor. 168 | 169 | d. Nothing in this Public License constitutes or may be interpreted as a limitation upon, or waiver of, any privileges and immunities that apply to the Licensor or You, including from the legal processes of any jurisdiction or authority. 170 | 171 | > Creative Commons is not a party to its public licenses. Notwithstanding, Creative Commons may elect to apply one of its public licenses to material it publishes and in those instances will be considered the “Licensor.” Except for the limited purpose of indicating that material is shared under a Creative Commons public license or as otherwise permitted by the Creative Commons policies published at [creativecommons.org/policies](http://creativecommons.org/policies), Creative Commons does not authorize the use of the trademark “Creative Commons” or any other trademark or logo of Creative Commons without its prior written consent including, without limitation, in connection with any unauthorized modifications to any of its public licenses or any other arrangements, understandings, or agreements concerning use of licensed material. For the avoidance of doubt, this paragraph does not form part of the public licenses. 172 | > 173 | > Creative Commons may be contacted at [creativecommons.org.](https://creativecommons.org/) 174 | --------------------------------------------------------------------------------