Closed caviri closed 1 year ago
Hello,
Thank you! There's still a lot of work to be done to improve it but it has been difficult to find the time.
Yes, it should work with a replicated folder structure. From an L2A product, KappaMask expects the following bands:
"AOT", "B01", "B02", "B03", "B04", "B05", "B06", "B07", "B08", "B8A", "B09", "B11", "B12", "WVP"
from an L1C product it expects:
"B01", "B02", "B03", "B04", "B05", "B06", "B07", "B08", "B8A", "B09", "B10", "B11", "B12"
If you're using the sentinelhub[AWS]
python package to fetch the rasters, then with the safe_format=True
argument it would replicate the .SAFE
directory structure.
For example, https://github.com/kappazeta/km_predict/blob/main/docker/km_predict/get_s3.py
Best regards
Thanks a lot. I did not know about the safe_format
parameter. However, I'm downloading the assets directly using pystac_client.
I'll try to write a script for the L2A product to create the folder structure. As soon as I have it, I will leave here in this issue.
Hello, I got a hacky method working I would like to share. I have been doing test with assets
downloaded using pystac_client
from aws
and microsoft planetary computer
. The former doesn't work as AOT
band is not at the correct resolution (A solution for this will be to download directly the .SAFE
folder as suggested by @indrek-sunter above. On the other hand MS contains all the bands in the correct resolution. However, we need to "fake" the folder structure on ".SAFE".
Here you can find the script I use to generate the folder and then create the symbolic links to the jp2
files. Assuming you have all JP2s in a folder named like the Sentinel 2 product, you can execute this like createFolderSymbolicsLinks({FolderContainingJP2s}, "/home/km_predict/data")
import os
import subprocess
def getAllJP2(folder):
jp2s = [file for file in os.listdir(folder) if file.endswith('.jp2')]
return jp2s
def makeSymbolicPath(originalPath, symbolicPath):
command = f'ln -s {originalPath} {symbolicPath}'
process = subprocess.Popen(command.split(), stdout=subprocess.PIPE)
output, error = process.communicate()
return output, error
def createFolderSymbolicsLinks(productFolder, outputFolder):
productName = productFolder.split("/")[-1]
jp2s = getAllJP2(productFolder)
if len(jp2s) == 15:
safeProductPath = os.path.join(outputFolder, productName + ".SAFE")
#if not os.path.exists(productPath): os.mkdir(productPath)
if not os.path.exists(safeProductPath): os.mkdir(safeProductPath)
granulePath = os.path.join(safeProductPath, "GRANULE")
os.mkdir(granulePath)
l2aPath = os.path.join(granulePath, "L2A")
os.mkdir(l2aPath)
imgdata = os.path.join(l2aPath, "IMG_DATA")
os.mkdir(imgdata)
qidata = os.path.join(l2aPath, "QI_DATA")
os.mkdir(qidata)
r10mPath = os.path.join(imgdata, "R10m")
r20mPath = os.path.join(imgdata, "R20m")
r60mPath = os.path.join(imgdata, "R60m")
os.mkdir(r10mPath)
os.mkdir(r20mPath)
os.mkdir(r60mPath)
for bandFile in jp2s:
bandPath = os.path.join(productFolder, bandFile)
res = bandFile.split(".")[0].split("_")[-1]
if res == "10m":
symbolicPath = os.path.join(r10mPath, bandFile)
output, error = makeSymbolicPath(bandPath, symbolicPath)
elif res == "20m":
symbolicPath = os.path.join(r20mPath, bandFile)
output, error = makeSymbolicPath(bandPath, symbolicPath)
elif res == "60m":
symbolicPath = os.path.join(r60mPath, bandFile)
output, error = makeSymbolicPath(bandPath, symbolicPath)
return productName
else:
print(f"Not enough files in {productFolder}")
Thanks again @indrek-sunter for the amazing tool. It's working great.
Hello,
First of all thanks a lot for making this project open, it looks awesome. I was wondering if a list of bands can be provided instead of the
.SAFE
folder. In my case, I have a list ofjp2
for each band of L2A.Otherwise, If I replicate the folder structure will it works?
Thanks