Alternative version based on Fiona library

Fiona is vector data library - Python layer on top of GDAL (OGR).

It can be interesting, to create independent Python modules, which will solve the geospatial issues out of the QGIS environment. Therefore, we are going to present different approach of the same data transformation task.

Qt Designer

We are going to add a new graphical element - radio button switcher to choose between QGIS tools and Fiona for the data transformation.

Úkol

Create radiobutton group for QGIS or Fiona. Use QRadioButton for the two elements. Use objectName again for naming the two radio buttons.

Select the two radiobuttons and right-click with mouse and create a new button group.

../_images/qt_designer_04.png

The code

Selecting proper tool

Checking, which radiobutton is checked, is quite easy:

            conversion_tool = "qgis"
            if self.dlg.fiona.isChecked():
                conversion_tool = "fiona"

For further selection of proper tool:

    if tool == "qgis":
        from .qgis_convertor import convert as target_convert
    else:
        from .fiona_convertor import convert as target_convert

Attribute data types

QGIS and Fiona do use different data type definition. We re-use our DATA_TYPES structure and add definition to Fiona

DATA_TYPES = {
    "demand_points": {
        "geometry": {
            "type": "Point"
        },
        "properties": OrderedDict([
            ("gistool_id", (QVariant.Int, "int")),
            ("include", (QVariant.Bool, "bool")),
            ("connection", (QVariant.String, "str")),
            ("pon_adop", (QVariant.Double, "float")),
            ("p2p_adop", (QVariant.Double, "float")),
            ("pon_homes", (QVariant.Int, "int")),
            ("p2p_homes", (QVariant.Int, "int")),
            ("pon_m_rev", (QVariant.Double, "float")),
            ("p2p_m_rev", (QVariant.Double, "float")),
            ("bldg_id", (QVariant.String, "str")),
            ("streetname", (QVariant.String, "str")),
            ("identifier", (QVariant.String, "str")),
            ("floorcount", (QVariant.Int, "int")),
            ("locked", (QVariant.Bool, "bool")),
            ("forced_cbl", (QVariant.String, "str"))
        ])
    }
}

Fiona

Fiona is Python library for reading and writing vector data. It internally converts the data structures into GeoJSON data format.

import fiona

with fiona.open("file.shp") as input_file:
    for feature in input_file:
        print(feature["properties"]["name"])
        print(feature["geometry"]["type"])

# ...

with fiona.open("out_file.shp", "w", crs="EPSG:4326",
                driver="ESRI Shapefile", schema=schema) as out:
    out.writerecords(features)

In our scenario, we need to open input data source, convert the attributes according to mapping file and save it to target data file.

Creating new data source

For new data source schema has to be specified, where geometry type and attribute types have to be set. The schema is a simple JSON structure:

schema = {
    'geometry': "Point",
    "properties": {
        "name": "str:25",
        "size": "int"
    }
}

Reading data from CSV structure

For CSV file manipulation csv python module can be used.

Creating new feature

As mentioned, Fiona uses GeoJSON structure for vector data manipulation. Creating a new features can be straight-forward:

feature = {
    "properties": {
        "name": "Oto",
        "size": 20
    },
    "geometry": {
        "type": "Point",
        "coordinates": [15, 50]
    }
}

Úkol

Create new ESRI Shapefile based on input CSV file and mapping file. After the file is created, use

vl = QgsVectorLayer(file_name, layer_name, "ogr")
QgsProject.instance().addMapLayer(vl)

For adding newly created layer to current QGIS project.