4

The data I have are ESRI Floating Point Data (so they are a raster type). The path I provided is a fake path, so that I don't show my real system paths.

I know that my code works with vector data, as I wrote this script, just for other data-types (.shp, .gpkg). Therefore, I assume, that the algorithm doesn't work with the flt-type.

... and indeed it doesn't. For reprojecting raster data, there is the algorithm warp.

So what I did yesterday was to use batch processing for applying the warp-function to the flt-data. The decision to not adapt the python script to warp the data but to use the batch-processing-functionality was just that it was a good opportunity to try it out (never worked with batches before).


I have a couple of .flt-files and I would like to reproject them to another CRS. In QGIS desktop, you can load the .flt-files by just dragging and dropping the file.

However, when I try to load the files in PyQGIS it says:

Could not load source layer for INPUT: path/to/3257559305385.flt not found

My code is just a function which uses the processing module. Is it somehow possible to load .flt-data in PyQGIS?

def reprojectFLTfiles(inputfolderpath, outputfolderpath, crs):
    for fltfile_name in os.listdir(inputfolderpath):
        if '.flt' in fltfile_name:
            if 'xml' not in fltfile_name:
                print(fltfile_name)
                INPUT = inputfolderpath + '/' + fltfile_name
                OUTPUT = outputfolderpath + '/' + fltfile_name
                print(INPUT)
                print(OUTPUT)
                processing.run("qgis:reprojectlayer",
                               {'INPUT':INPUT,
                                'TARGET_CRS':crs,
                                'OUTPUT':OUTPUT
                               }
                )

2
  • 2
    It seems that the full path to the source file is not being created correctly. What does inputfolderpath look like? Does the print statement print the the correct INPUT path string? Can you verify it with os.path.exists()? As a better practice, I would encourage you to use os.path.join() instead of the string arithmetic.
    – Ben W
    Feb 19 at 11:36
  • The path is not the real path but just to prevent to show my system-path in public. I have updated the question accordingly.
    – i.i.k.
    Feb 20 at 8:20

1 Answer 1

6

I would agree with @BenW's comment, that your binary floating-point files can not be found under this path inputfolderpath + '/' + fltfile_name. However, I could also say, that your input does not match any of the INPUT accepted data types. See, that "Reproject layer" geoalgorithm reprojects a vector layer in a different CRS. See the GDAL Vector drivers for more details.

⚠️ For raster data types, use the "Warp (reproject)", see the GDAL Raster drivers for more details.

Your binary floating-point file with a .flt extension should come with an ASCII header file that has a .hdr extension, see EHdr -- ESRI .hdr Labelled. You only specify the .flt file; however, there needs to be an existing .hdr file in the same directory with the same file name.


There are several suggestions to your code:

  • check firstly alg input and output by means of the processing.algorithmHelp("qgis:reprojectlayer")

    INPUT: Input layer
    
        Parameter type:  QgsProcessingParameterFeatureSource
    
        Accepted data types:
            - str: layer ID
            - str: layer name
            - str: layer source
            - QgsProcessingFeatureSourceDefinition
            - QgsProperty
            - QgsVectorLayer
    
    OUTPUT: Reprojected
    
        Parameter type:  QgsProcessingParameterFeatureSink
    
        Accepted data types:
            - str: destination vector file, e.g. 'd:/test.shp'
            - str: 'memory:' to store result in temporary memory layer
            - str: using vector provider ID prefix and destination URI, e.g. 'postgres:…' to store result in PostGIS table
            - QgsProcessingOutputLayerDefinition
            - QgsProperty
    
  • apply the isfile() function from the os.path library to check if a file exists

    if isfile(INPUT):
       ...
    

    Or, as was mentioned by @BenW, apply the exists() function. This function isdir() can also be handy for dirs.

  • better to work with a normalized path, can be achieved with the normpath() function

    for fltfile_name in listdir(normpath(inputfolderpath)):
    
  • two if-statements can be combined into one

    if '.flt' in fltfile_name and not ('xml' in fltfile_name):
       ...   
    
  • make use of the join() function to get a proper file path

    INPUT = join(inputfolderpath, fltfile_name)
    
  • use the Python Try Except blocks to handle errors and exceptions e.g. QgsProcessingException.

             try:
                 params = {
                     'INPUT': INPUT,
                     'TARGET_CRS': crs,
                     'OUTPUT': OUTPUT
                 }
                 processing.run("qgis:reprojectlayer", params)
                 return True
             except QgsProcessingException:
                 return False
    

    The QGIS processing algorithm also has a checkParameterValues()-method:

    Checks the supplied parameter values to verify that they satisfy the requirements of this algorithm in the supplied context.

    The message parameter will be filled with explanatory text if validation fails. Overridden implementations should also check this base class implementation.

  • it is not clear yet in which form you provide the crs value, but there is a class QgsCoordinateReferenceSystem(), that facilitates creation and work with CRS

    crs = QgsCoordinateReferenceSystem.fromEpsgId(4326)
    
  • imports can be useful to make your code reusable in the future in standalone applications

    # imports
    import processing
    from qgis.core import QgsCoordinateReferenceSystem
    from os import listdir
    from os.path import isfile, join, normpath
    
  • add some reprojectFLTfiles descriptions, see the PEP 20 – The Zen of Python for more inspiration

    def reprojectFLTfiles(inputfolderpath: str, outputfolderpath: str, crs: int) -> bool:
        """
        Reprojects a FTL file using a certain CRS
        Parameters:
        ==========
        :param inputfolderpath:
        :param outputfolderpath:
        :param crs:
        Returns:
        ==========
        :return: 
        """
    

So, in the end, it may look like this:

# imports
import processing
from qgis.core import QgsCoordinateReferenceSystem
from os import listdir
from os.path import isfile, join, normpath


def reprojectFLTfiles(inputfolderpath: str, outputfolderpath: str, epsg_code: int) -> bool:
    """
    Reprojects FTL file to a certain CRS
    Parameters:
    ==========
    :param inputfolderpath:
    :param outputfolderpath:
    :param crs:
    Returns:
    ==========
    :return:
    """

    crs = QgsCoordinateReferenceSystem.fromEpsgId(epsg_code)

    for fltfile_name in listdir(inputfolderpath):
        if '.gpkg' in fltfile_name and not ('xml' in fltfile_name):
            INPUT = join(inputfolderpath, fltfile_name)
            if isfile(INPUT):
                OUTPUT = join(outputfolderpath, fltfile_name)
                try:
                    params = {
                        'INPUT': INPUT,
                        'TARGET_CRS': crs,
                        'OUTPUT': OUTPUT
                    }
                    processing.run("qgis:reprojectlayer", params)
                    return True
                except QgsProcessingException as e:
                    print(f'Could not reproject this {INPUT} file. Ended with the following error:')
                    print(e)
                    return False


reprojectFLTfiles('D:/qgis_test/', 'D:/qgis_test/temp/', 4326)

With the code above, I could reproject my GeoPackage from EPSG:32637 into EPSG:4326.


References:

1
  • Thank you so much for the effort! Very helpful, however, I didn't specify the flt-data: it are floating-point-data from ESRI. I updated the question accordingly!
    – i.i.k.
    Feb 20 at 8:22

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.