├── 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
[](https://creativecommons.org/licenses/by-nc-sa/4.0/) [](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 | 
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 | 
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) 
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 |
--------------------------------------------------------------------------------