Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Processing on AWS #107

Open
rodolfolotte opened this issue Mar 16, 2020 · 16 comments
Open

Processing on AWS #107

rodolfolotte opened this issue Mar 16, 2020 · 16 comments

Comments

@rodolfolotte
Copy link

Just did a small example for stacking Sentinel-1 images, but something is still wrong!

The method is mostly what is presented in this repository's example:

def stack_images(images_path, aoi):
    """
    :param images_path:
    :return:
    """
    absolute_path = os.path.abspath(images_path)
    output_mosaic_path = absolute_path.replace('filter', 'stack')
    aois_path = settings.DATASET_PATH + 'radar/aoi/shp/'
    output_shp_file = aois_path + aoi + ".shp"

    srcfiles = finder(images_path, ['^S1[AB]'], regex=True, recursive=False)
    groups = groupbyTime(srcfiles, seconds, 30)

    try:
        os.makedirs(output_mosaic_path)
    except FileExistsError:
        pass

    stack(srcfiles=groups, dstfile=output_mosaic_path + "/" + 'stack.tiff', resampling='bilinear',
          targetres=[20, 20], srcnodata=0, dstnodata=-99,
          shapefile=output_shp_file, sortfun=seconds, separate=False, overwrite=True)

Just to make clear, the srcfiles variable brings all original sentinel images:

['.../iw-vh/S1A_IW_GRDH_1SDV_20180525T093134_20180525T093159_022059_026254_0ED2_iw-vh.tiff', '/.../iw-vh/S1A_IW_GRDH_1SDV_20180525T093159_20180525T093224_022059_026254_DE25_iw-vh.tiff', '.../iw-vh/S1A_IW_GRDH_1SDV_20180525T093224_20180525T093249_022059_026254_28B8_iw-vh.tiff', '.../iw-vh/S1A_IW_GRDH_1SDV_20180530T093955_20180530T094020_022132_0264A6_04BA_iw-vh.tiff', '.../iw-vh/S1A_IW_GRDH_1SDV_20180530T094020_20180530T094045_022132_0264A6_A27A_iw-vh.tiff', '.../iw-vh/S1A_IW_GRDH_1SDV_20180530T094045_20180530T094110_022132_0264A6_D444_iw-vh.tiff']

but still getting this error:

Traceback (most recent call last):
  File "/home/rodolfo/Bit/lotte/aws-imagery/.venv/lib/python3.7/site-packages/spatialist/auxil.py", line 63, in crsConvert
    srs.SetFromUserInput(crsIn)
  File "/home/rodolfo/Bit/lotte/aws-imagery/.venv/lib/python3.7/site-packages/osgeo/osr.py", line 1068, in SetFromUserInput
    return _osr.SpatialReference_SetFromUserInput(self, *args)
RuntimeError: OGR Error: Corrupt data

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "aws_cli.py", line 114, in <module>
    main(args.ranges)
  File "aws_cli.py", line 70, in main
    dip.stack_images(path_to_pol, aoi)
  File "/home/rodolfo/Bit/lotte/aws-imagery/aws_process.py", line 82, in stack_images
    shapefile=output_shp_file, sortfun=seconds, separate=False, overwrite=True)
  File "/home/rodolfo/Bit/lotte/aws-imagery/.venv/lib/python3.7/site-packages/spatialist/raster.py", line 1231, in stack
    group = [x for x in group if intersect(shp, Raster(x).bbox())]
  File "/home/rodolfo/Bit/lotte/aws-imagery/.venv/lib/python3.7/site-packages/spatialist/raster.py", line 1231, in <listcomp>
    group = [x for x in group if intersect(shp, Raster(x).bbox())]
  File "/home/rodolfo/Bit/lotte/aws-imagery/.venv/lib/python3.7/site-packages/spatialist/raster.py", line 426, in bbox
    return bbox(coordinates=extent, crs=crs)
  File "/home/rodolfo/Bit/lotte/aws-imagery/.venv/lib/python3.7/site-packages/spatialist/vector.py", line 725, in bbox
    srs = crsConvert(crs, 'osr')
  File "/home/rodolfo/Bit/lotte/aws-imagery/.venv/lib/python3.7/site-packages/spatialist/auxil.py", line 66, in crsConvert
    '  was: "{}" of type {}'.format(crsIn, type(crsIn).__name__))
TypeError: crsIn not recognized; must be of type WKT, PROJ4 or EPSG
  was: "" of type str

Seems to be some projection missing data! But I'm using original image and check with another softwares, which gave me the correct metadata!

@johntruckenbrodt
Copy link
Owner

Hi @rodolfolotte,
the function stack is intended to be used on geocoded Sentinel-1 data only. The original GeoTiffs you are using do only contain a few GCPs with a projection, but the image itself is not geocoded. You can pre-process the images using SNAP with pyroSAR's Python API.
Please have a look at this section in the documentation and the call of function geocode in particular.
Cheers, John

@rodolfolotte
Copy link
Author

rodolfolotte commented Mar 17, 2020

Hey John @johntruckenbrodt ! Thank you so much! I will have a look! Had no idea about this... Many thanks for updating!
Cheers!

@johntruckenbrodt
Copy link
Owner

Sure, you're welcome. I am closing this for now but feel free to reopen it if you encounter something similar.

@rodolfolotte
Copy link
Author

rodolfolotte commented Mar 17, 2020

@johntruckenbrodt , I'm sorry! Just one more question!

The stacking example provided in the repository (see below), does not make any adjust to geocode the images. Why in this case the geocode method is not required?

def main():
    # define input directory containing file sto be stacked
    dir_in = '/...'
    
    # define output file name
    dstfile = '/.../x'
    
    # shapefile (for stack boundaries)
    shp = '/../x.shp'
    
    # store results in separate files or one single stack file? If separate then dstfile is used as a directory.
    sep = True
    
    # list files to be resampled; those not overlapping with the shapefile geometry will excluded by function stack
    srcfiles = finder(dir_in, ['S1*_VV_*norm_db.tif'])
    
    # check whether dstfile is already a file
    if os.path.isfile(dstfile):
        raise IOError('dstfile already exists')
    
    # create groups of similar time stamps for mosaicking.
    # All images with a time stamp of less than 30s difference will be grouped
    groups = groupbyTime(srcfiles, seconds, 30)
    
    # final function call
    # groups will be mosaicked first
    # the resulting images will all have the same extent
    stack(srcfiles=groups, dstfile=dstfile, resampling='bilinear',
          targetres=[20, 20], srcnodata=-99, dstnodata=-99,
          shapefile=shp, sortfun=seconds, separate=sep, overwrite=False)

This example is runnable or it is just there to give "an idea" how to use?

The geocode method demands the infile to be either a list, ID or str. However, when i pass a list of absolute paths to .tiff Sentinel-1 images, it says RuntimeError: data format not supported.

So, my doubt is: I do need to use SNAP to search and download S1 images, or I'm still missing something. PS. I'm currently using S3 AWS as source.

@johntruckenbrodt
Copy link
Owner

Hi. This example stacks images already processed with pyroSAR geocode. The following line collects all images in VV polarization which have been topographically normalized (_norm) and logarithmically scaled to decibel (_db):

srcfiles = finder(dir_in, ['S1*_VV_*norm_db.tif'])

This example is runnable as long as you have a directory containing several images processed by function geocode.
You do not need SNAP to search and download scenes. In fact, it is not possible. Rather, SNAP expects scenes in some locally accessible directory and then processes these scenes, i.e. applies several conversion steps. The output are e.g. calibrated, geocoded and normalized scenes e.g. in GeoTiff format. If the scenes are available on S3 then I am sure you can directly pass them to SNAP. I have not worked on Amazon yet but am sure there are many examples out there of how to do it. The STEP Forum is a good resource for information in case you don't know it yet.
It would be interesting to know whether the function geocode works well with the S3 file system. So it would be great if you could let me know whether you get it to work.
Cheers, John

@rodolfolotte
Copy link
Author

Hi @johntruckenbrodt Thank you!

Look, my function is like:

def stack_images(images_path, aoi):
    """
    :param images_path:
    :return:
    """
    absolute_path = os.path.abspath(images_path)
    output_mosaic_path = absolute_path.replace('filter', 'stack')
    aois_path = settings.DATASET_PATH + 'radar/aoi/shp/'
    output_shp_file = aois_path + aoi + ".shp"
    check_output_dirs(output_mosaic_path)

    list_images = build_list_of_images(images_path)

    geocode(infile=list_images, outdir='/data/tmp/2018-05-24_2018-05-30', tr=20, scaling='dB',
            export_extra=['DEM', 'localIncidenceAngle'], t_srs=4326, shapefile=output_shp_file)    

where list_images give me a list of str absolute paths to the .tiff files.

Then, I get this message:

File "/home/rodolfo/Bit/lotte/aws-imagery/.venv/lib/python3.7/site-packages/pyroSAR/snap/util.py", line 162, in geocode
    id = ids[0]
IndexError: list index out of range

I just debuged! Seems to be something regarding the image projection, or probably the file extension! Because the empty variable ids is load by function pyroSAR.identify_many(infile, verbose=False, sortkey='start') in util.py. Which uses the identify(scene) function. So, I conclude if I do not have the file in .zip extension, i will not be able to load any data!

I'm correct?

@johntruckenbrodt
Copy link
Owner

A SAR scene usually consists of one or more image files and in most cases several text files containing metadata. If you want to process a SAR scene with the geocode function, you need to provide the whole scene. In the case of Sentinel-1 this is either the .zip archive as downloaded from e.g. the Copernicus Open Access Hub or the folder ending with .SAFE.
So instead of the direct path to the individual .tiff files, provide a list of paths to the .zip or .SAFE SAR scene locations. Beware however, that a list of SAR scenes is "treated as consecutive acquisitions, which will be mosaicked with SNAP’s SliceAssembly operator" as described in the geocode documentation. If your list of scenes spans a larger time frame, it is better to first group them using function groupbyTime and then pass each group to geocode:

from pyroSAR.snap import geocode
from pyroSAR.ancillary import groupbyTime, seconds
from spatialist.ancillary import finder
list_images = finder('/location', ['*.SAFE'], foldermode=2)
list_images = groupbyTime(images=list_images, function=seconds, time=30)
for group in list_images:
    geocode(group, ...)

The function spatialist.finder is just for demonstration, but seems not to work for AWS S3 yet as discussed in issue johntruckenbrodt/spatialist#10.

@rodolfolotte
Copy link
Author

@johntruckenbrodt Ok! Then, i will have a look at SAFE packages in S3 buckets. If I get it done, I will post it here! Thank you so much!

@rodolfolotte
Copy link
Author

rodolfolotte commented Apr 15, 2020

Well, almost there! Hey, @johntruckenbrodt, how are you?

I'm sorry to insist on this, but I think we will have a nice contribution after link pyroSAR to use together with AWS repositories.

Well, I could not find any other bucket in S3 that could provide to be .zip or SAFE formats, even in sentinel-s1-l1c-zip, where suppose to have those formats. Anyway, I just did the SAFE folder by myself (of course, following the conventions in Sentinel-1 SAFE format), file by file (I intend to commit the whole procedure later, in a separated repository):

annotation
│   ├── calibration
│   │   ├── calibration-s1a-iw-grd-vh-20180708t100534-20180708t100559-022701-0275c2-001.xml
│   │   ├── calibration-s1a-iw-grd-vv-20180708t100534-20180708t100559-022701-0275c2-002.xml
│   │   ├── noise-s1a-iw-grd-vh-20180708t100534-20180708t100559-022701-0275c2-003.xml
│   │   └── noise-s1a-iw-grd-vv-20180708t100534-20180708t100559-022701-0275c2-004.xml
│   ├── s1a-iw-grd-vh-20180708t100534-20180708t100559-022701-0275c2-001.xml
│   └── s1a-iw-grd-vv-20180708t100534-20180708t100559-022701-0275c2-002.xml
├── manifest.safe
├── measurement
│   ├── s1a-iw-grd-vh-20180708t100534-20180708t100559-022701-0275c2-001.tiff
│   └── s1a-iw-grd-vv-20180708t100534-20180708t100559-022701-0275c2-002.tiff
├── preview
│   ├── icons
│   │   └── logo.png
│   ├── map-overlay.kml
│   ├── product-preview.html
│   └── quick-look.png
└── support
    ├── s1-level-1-calibration.xsd
    ├── s1-level-1-measurement.xsd
    ├── s1-level-1-noise.xsd
    ├── s1-level-1-product.xsd
    ├── s1-level-1-quicklook.xsd
    ├── s1-map-overlay.xsd
    ├── s1-object-types.xsd
    └── s1-product-preview.xsd

6 directories, 21 files

Once the folders are done, I compressed (.zip) each of them and finally got the inputs to use pyroSAR.geocode. Still, I'm getting some complications. Ok, so, I really don't know if this error occurs due to missing informations in SAFE folder, or even a bad use of SNAP library.

searching for new POE files
https://qc.sentinel1.eo.esa.int/api/v1/?product_type=AUX_POEORB&sentinel1__mission=S1A&validity_start__gte=2018-07-02T09:57:32&validity_stop__lte=2018-07-04T09:57:32
100% (1 of 1) |#######################################################################################################################################################################################################################| Elapsed Time: 0:00:00 Time:  0:00:00
downloading 1 file
100% (1 of 1) |#######################################################################################################################################################################################################################| Elapsed Time: 0:00:00 Time:  0:00:00
deleting 0 RES files
unpacking scene
removing border noise..
border noise removal not necessary for IPF version 2.91
executing node sequences..
Subset
['/opt/snap/bin/gpt', '-e', '/tmp/2018-05-24_2018-07-23/aoi_1/stack/S1A_IW_GRDH_1SDV_20180703T095732_20180703T095754_022628_0273A0_22FF/S1A__IW___D_20180703T095732_tnr_bnr_Orb_Cal_ML_TF_TC_dB/temp/S1A_IW_GRDH_1SDV_20180703T095732_20180703T095754_022628_0273A0_22FF_tmp0.xml']
ThermalNoiseRemoval
['/opt/snap/bin/gpt', '-e', '/tmp/2018-05-24_2018-07-23/aoi_1/stack/S1A_IW_GRDH_1SDV_20180703T095732_20180703T095754_022628_0273A0_22FF/S1A__IW___D_20180703T095732_tnr_bnr_Orb_Cal_ML_TF_TC_dB/temp/S1A_IW_GRDH_1SDV_20180703T095732_20180703T095754_022628_0273A0_22FF_tmp1.xml']
Executing processing graph
90% done.
INFO: org.esa.snap.core.gpf.operators.tooladapter.ToolAdapterIO: Initializing external tool adapters
INFO: org.esa.snap.core.util.EngineVersionCheckActivator: Please check regularly for new updates for the best SNAP experience.
INFO: org.hsqldb.persist.Logger: dataFileCache open start
org.esa.snap.core.gpf.OperatorException
        at org.esa.snap.core.gpf.graph.GraphProcessor$GPFImagingListener.errorOccurred(GraphProcessor.java:363)
        at com.sun.media.jai.util.SunTileScheduler.sendExceptionToListener(SunTileScheduler.java:1646)
        at com.sun.media.jai.util.SunTileScheduler.scheduleTile(SunTileScheduler.java:921)
        at javax.media.jai.OpImage.getTile(OpImage.java:1129)
        at javax.media.jai.PlanarImage.getData(PlanarImage.java:2085)
        at com.bc.ceres.glevel.MultiLevelImage.getData(MultiLevelImage.java:64)
        at org.esa.snap.core.gpf.internal.OperatorContext.getSourceTile(OperatorContext.java:407)
        at org.esa.snap.core.gpf.internal.OperatorContext.getSourceTile(OperatorContext.java:393)
        at org.esa.snap.core.gpf.internal.OperatorImage.computeRect(OperatorImage.java:73)
        at javax.media.jai.SourcelessOpImage.computeTile(SourcelessOpImage.java:137)
        at com.sun.media.jai.util.SunTileScheduler.scheduleTile(SunTileScheduler.java:904)
        at javax.media.jai.OpImage.getTile(OpImage.java:1129)
        at com.sun.media.jai.util.RequestJob.compute(SunTileScheduler.java:247)
        at com.sun.media.jai.util.WorkerThread.run(SunTileScheduler.java:468)
Caused by: org.esa.snap.core.gpf.OperatorException
        at org.esa.s1tbx.calibration.gpf.Sentinel1RemoveThermalNoiseOp.computeTile(Sentinel1RemoveThermalNoiseOp.java:623)
        at org.esa.snap.core.gpf.internal.OperatorImage.computeRect(OperatorImage.java:80)
        at javax.media.jai.SourcelessOpImage.computeTile(SourcelessOpImage.java:137)
        at com.sun.media.jai.util.SunTileScheduler.scheduleTile(SunTileScheduler.java:904)
        ... 11 more

Error: org.esa.snap.core.gpf.OperatorException
SEVERE: org.esa.snap.core.util.SystemUtils$SnapImagingListener: JAI error occurred: 'Problem occurs when computing a tile by the owner.' at com.sun.media.jai.util.SunTileScheduler@4a9b3371
org.esa.snap.core.gpf.OperatorException
        at org.esa.s1tbx.calibration.gpf.Sentinel1RemoveThermalNoiseOp.computeTile(Sentinel1RemoveThermalNoiseOp.java:623)
        at org.esa.snap.core.gpf.internal.OperatorImage.computeRect(OperatorImage.java:80)
        at javax.media.jai.SourcelessOpImage.computeTile(SourcelessOpImage.java:137)
        at com.sun.media.jai.util.SunTileScheduler.scheduleTile(SunTileScheduler.java:904)
        at javax.media.jai.OpImage.getTile(OpImage.java:1129)
        at javax.media.jai.PlanarImage.getData(PlanarImage.java:2085)
        at com.bc.ceres.glevel.MultiLevelImage.getData(MultiLevelImage.java:64)
        at org.esa.snap.core.gpf.internal.OperatorContext.getSourceTile(OperatorContext.java:407)
        at org.esa.snap.core.gpf.internal.OperatorContext.getSourceTile(OperatorContext.java:393)
        at org.esa.snap.core.gpf.internal.OperatorImage.computeRect(OperatorImage.java:73)
        at javax.media.jai.SourcelessOpImage.computeTile(SourcelessOpImage.java:137)
        at com.sun.media.jai.util.SunTileScheduler.scheduleTile(SunTileScheduler.java:904)
        at javax.media.jai.OpImage.getTile(OpImage.java:1129)
        at com.sun.media.jai.util.RequestJob.compute(SunTileScheduler.java:247)
        at com.sun.media.jai.util.WorkerThread.run(SunTileScheduler.java:468)


[S1A_IW_GRDH_1SDV_20180703T095732_20180703T095754_022628_0273A0_22FF_tmp1.xml] failed with return code 1
failed: /tmp/2018-05-24_2018-07-23/aoi_1/stack/S1A_IW_GRDH_1SDV_20180703T095732_20180703T095754_022628_0273A0_22FF/S1A__IW___D_20180703T095732_tnr_bnr_Orb_Cal_ML_TF_TC_dB/S1A__IW___D_20180703T095732_tnr_Orb_Cal_ML_TF_TC_dB_proc.xml
scene S1A__IW___D_20180708T100509 already processed

Thank you so much!

@rodolfolotte
Copy link
Author

rodolfolotte commented Apr 16, 2020

@johntruckenbrodt I just found the problem!

I was not fully agreement to the SAFE format. The following files:

noise-s1a-iw-grd-vh-20180708t100534-20180708t100559-022701-0275c2-003.xml
noise-s1a-iw-grd-vv-20180708t100534-20180708t100559-022701-0275c2-004.xml

were nominated incorrectly (final integer). For this reason, the SNAP, either pyroSAR.geocode, had some mismatching!

Before doing some reverse engineering, just asking: would you mind to share the details (theory, not code) of each workflow steps (could be papers, or any other link): Subset, ThermalNoiseRemoval, Apply-Orbit-File, Calibration, Multilook, Terrain-Flattening, Terrain-Correction, and LinearToFromdB?

Thank you!

@rodolfolotte
Copy link
Author

Probably here:

  • J. Truckenbrodt, F. Cremer, I. Baris, and J. Eberle. Pyrosar: a framework for large-scale sar satellite data processing. In P. Soille, S. Loekken, and S. Albani, editors, Big Data from Space, 197–200. Luxembourg, 2019. Publications Office of the European Union. doi:10.2760/848593.
  • J. Truckenbrodt, T. Freemantle, C. Williams, T. Jones, D. Small, C. Dubois, C. Thiel, C. Rossi, A. Syriou, and G. Giuliani. Towards sentinel-1 sar analysis-ready data: a best practices assessment on preparing backscatter data for the cube. Data, 2019. doi:10.3390/data4030093.

;)

@johntruckenbrodt
Copy link
Owner

Hi @rodolfolotte,
thanks a lot for sharing our insights. I fully agree that it would be a very important improvement if pyroSAR would easily work on AWS.
I am wondering though if packing the scenes into a .zip structure is really necessary. Maybe we can find an easier way. I ended up creating my own AWS machine to play around a little, although I am just starting with it. I found this S3 bucket sentinel-s1-l1c which seems to contain all the unpacked scenes. I was expecting them to be in directories ending with .SAFE, but they are not. The rest of the name is the same though.
In pyroSAR the .SAFE suffix is currently hard coded here. I think if I make it optional the scene could potentially be read. Although in total more code needs to be adapted because all the file search tools are not compatible with S3.
Finally, the following should work to read a SAR scene in pyroSAR (described here):

from pyroSAR import identify
location = 's3://sentinel-s1-l1c/GRD/2018/11/11/IW/SV/'
name = 'S1B_IW_GRDH_1SSV_20181111T171503_20181111T171532_013559_019191_0F09'
scene = identify(location + name)
print(scene)

How are you searching for scenes in the S3 buckets? It would be very convenient if a user could just search for scenes based on some parameters, e.g. polarization and acquisition date, and get the result as a list that can then be passed to geocode similar to the example above.

Cheers,
John

@johntruckenbrodt johntruckenbrodt changed the title TypeError: crsIn not recognized; must be of type WKT, PROJ4 or EPSG Processing on AWS Apr 20, 2020
@rodolfolotte
Copy link
Author

rodolfolotte commented Apr 20, 2020

Hi @johntruckenbrodt, how are you?

Ok, I will give all insights about the "mismatchings" between pyroSAR.geocode and AWS environment.

Yes, you are right! The respective bucket offers all the individual itens (not SAFE format, either .zip packages), but with different names when you compare to the name conventions (see here). For example, the measurements brings the image discriminated by polarization and mode: iw-vv.tiff, instead of convention: mmm-sss-ttt-pp-yyyymmddthhmmss-yyyymmddthhmmss-oooooo-dddddd-nnn.eee (see here). So, this two main issues was solved!

I have checked the bucket sentinel-s1-l1c-zips, but could not download any file from there. So, I had to adapt my script to literaly build the SAFE folder, where each folder ('measurement', 'annotation', 'support', 'preview', 'manifest.safe') needs a particular request, due to the fact some of them has "subitens", such as 'annotation' with subfolder 'calibration'.

Then, I thought I should have this done but many other small issues have also to be adapted!

First, there is a problem with identify() on reading the ID scene. What I have noticed, is that depending the zip compression, it does not recognize the format (error: format not supported). I'm saying that because I used zipfile library. Something like:

import os
import zipfile 

def get_all_file_paths(directory):
    """
    :param directory:
    :return:
    """
    file_paths = []

    for root, directories, files in os.walk(directory):
        for filename in files:
            filepath = os.path.join(root, filename)
            file_paths.append(filepath)

    return file_paths

path_item_list = get_all_file_paths(path_item)
compress_file = path_item.replace(".SAFE", "") + ".zip"

with zipfile.ZipFile(compress_file, 'w', zipfile.ZIP_DEFLATED) as zip:
     for file in path_item_list:
         zip.write(file, file)
     zip.close()

to get the SAFE folder compressed. But I got that error massage. But if I compress with Ubuntu right click, then identify(), and consequently, geocode do the job. I have no idea why this happen. Format is ok, filename is ok, so... no clue! Thus, I'm trying to figure how to get the right compression like Linux bash does.

I want to share all what I've reached, although it is not tested at all (I mean, unittest). As I did not figured out how to deal with .zip issue, I will get a workaround and reply to you here! Then, we can think about a small PR.

Cheers! Many thanks!

@johntruckenbrodt
Copy link
Owner

Hi @rodolfolotte,
I'm doing fine, thanks. How about you? Crazy times right now.
This is more difficult than I was expecting. Strange sinergise is renaming the products. I also cannot find any information from them about this.
This issue with identify() is interesting. Could you try reading the scene directly with SAFE? This might give a little more insight into what's going wrong:

from pyroSAR.drivers import SAFE
name = 'S1B_IW_GRDH_1SSV_20181111T171503_20181111T171532_013559_019191_0F09'
scene = SAFE(name)
print(scene)

The function identify() just tries all drivers and raises a RuntimeError if none of them work.

Cheers, John

@rodolfolotte
Copy link
Author

Hello @johntruckenbrodt, everything is fine!

Yeah, pretty tough moment we are living! :/

Ok, so... I've created a new repository to search and download images from AWS. It s available here.

  • the zip issue was fixed by compressing with shutil. zipfile did not work out:
import os
import shutil

def make_archive(source, destination):
    """
    Source: http://www.seanbehan.com/how-to-use-python-shutil-make_archive-to-zip-up-a-directory-recursively-including-the-root-folder/
    :param source:
    :param destination:
    :return:
    """
    base = os.path.basename(destination)
    name = base.split('.')[0]
    format_file = base.split('.')[1]
    archive_from = os.path.dirname(source)
    archive_to = os.path.basename(source.strip(os.sep))
    shutil.make_archive(name, format_file, archive_from, archive_to)
    shutil.move('%s.%s' % (name, format_file), destination)


compress_file = path_item.replace(".SAFE", "") + ".zip"
utils.make_archive(path_item, compress_file)

  • geocode fails when processing with list of images (specifically, when uses identify_many()). This execption is raised:
File "../.venv/lib/python3.7/site-packages/pyroSAR/snap/auxil.py", line 884, in __set_source
    raise RuntimeError('cannot set source on {} node'.format(self.operator))
RuntimeError: cannot set source on SliceAssembly node

but if I pass image by image, then I get all the procedures done:

list_images = finder(images_path + "/", ['*.zip'])

if len(list_images) != 0:
	list_images_groups = groupbyTime(images=list_images, function=seconds, time=30)

	for i, images in enumerate(list_images_groups):
	    if isinstance(images, list):
		output_path_aux = output_path + "/group-images-" + str(i) + "/"
		utils.check_dir_exist(output_path_aux)

		for image in images:
		    geocode(image, outdir=output_path_aux, shapefile=output_shp_file)
	    else:
		filename = os.path.basename(images)
		filename = filename.split(".")[0]
		output_path_aux = output_path + "/" + filename + "/"

		geocode(images, outdir=output_path_aux, shapefile=output_shp_file)

Now, I'm facing a problem with stacking:

File "../aws-imagery/aws_process.py", line 126, in execute_stack
    shapefile=output_shp_file, sortfun=seconds, separate=False, overwrite=True)
  File "../aws-imagery/.venv/lib/python3.7/site-packages/spatialist/raster.py", line 1333, in stack
    gdalwarp(vrt, dstfile, options_warp, pbar=pbar)
  File "../aws-imagery/.venv/lib/python3.7/site-packages/spatialist/auxil.py", line 145, in gdalwarp
    raise RuntimeError('{}:\n  src: {}\n  dst: {}\n  options: {}'.format(str(e), src, dst, options))
RuntimeError: Attempt to create 0x0 dataset is illegal,sizes must be larger than zero.:
  src: /vsimem/stack.vrt
  dst: /tmp/2020-01-01_2020-01-13/aoi_3/stack/stack.tiff
  options: {'options': ['-q', '-overwrite', '-wo', 'NUM_THREADS=4', '-of', 'ENVI', '-te', '-61.181218526836048', '-8.58026931211235855', '-58.3581672726766598', '-5.70588985333189491', '-tr', '20', '20', '-r', 'bilinear', '-srcnodata', '0', '-dstnodata', '-99', '-multi'], 'format': 'ENVI', 'outputBounds': (-61.18121852683605, -8.580269312112359, -58.35816727267666, -5.705889853331895), 'multithread': True, 'dstNodata': -99, 'xRes': 20, 'yRes': 20, 'resampleAlg': 'bilinear', 'srcNodata': 0}

First, I thought it could be an overlapping issue, but it seems to be something else. I'm debbuging and still did not get a workaround! What I truly want to do with all this, is to get the mean of a set of images over a specific AOI. Let you know! ;)

Cheers!

@johntruckenbrodt
Copy link
Owner

Hi @rodolfolotte,
great to hear you're doing fine and that you are progressing with the repackaging!
I was not aware that it is possible to create zips with shutil, I will give it a look.
Passing a list of scenes to geocode is only intended for the case when all these scenes have been acquired right after each other and can thus be mosaicked with SNAP's SliceAssembly operator. The function groupbyTime can be used to group images for this. Each group can then be passed as a list to geocode. However only a list with two entries works for now. So unless your study area is really large and is covered by more than two scenes in one consecutive acquisition, you could do the following:

list_images_groups = groupbyTime(images=list_images, function=seconds, time=30)
for job in list_image_groups:
    geocode(job, ...)

One suggestion: use os.path.join for concatenating paths. So instead of this:

output_path_aux = output_path + "/group-images-" + str(i) + "/"

do this:

output_path_aux = os.path.join(output_path, "group-images-{}".format(i))

This way it works on all operating systems.
The error you receive from gdalwarp is related to the spatial resolution of your source and target products. You are processing your images in EPSG:4326 so your source resolution units are degrees. You are not changing your CRS during stacking so also the target product resolution is in degrees. Thus, you are defining your target resolution as 20x20 degrees and this is larger than your study area.
My colleagues and I are using the function spatialist.raster.stack for these purposes, maybe it is also helpful to you.

Cheers,
John

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants