[GIS] Batch csv import, styling and image export from QGIS

batchqgis

I have a folder of several hundred csv files with point data. I need to import each into QGIS as a layer, apply the same style to each, and then render a map (same extents) for each (these will be frames in a video). The tutorials I've been able to find for batch processing in QGIS refer to producing maps of different areas of the same layers (with the Print Composer Atlas tool) or running plugins / 3rd party algorithms (with the Processing Framework tool), but not to automating batch usage of the basic functions of QGIS (importing and styling layers, exporting images). Is there a way to do this?

Best Answer

I think I have this figured out! Thanks to Miro for pointing me to some relevant past qs. This is largely building on the script from this question: https://stackoverflow.com/questions/27033261/import-csv-into-qgis-using-python. This assumes that (1) you have a style .qml file in the same folder as all the .csvs and it's called style.qml; (2) that the csvs are numbered (in this case from 1250 to 1550) and each just called "x.csv"; (3) that you have a composer manager template made and open, with a label selected which will change to display the frame number. It creates images each named "frame x.png" in the same folder. Here's the code:

#--- get starting stuff
composers = iface.activeComposers()
c=composers[0].composition()
frameLabel=c.selectedComposerItems()[0]

#--- Load a csv file and set CRS
#---1 Reference library
from PyQt4.QtGui import *
from PyQt4.QtCore import *
from qgis.core import *
from qgis.utils import iface

for x in range(1220, 1550):
    #---  2 Turn of the CRS dialog box
    s = QSettings()
    oldValidation = s.value( "/Projections/defaultBehaviour")
    s.setValue( "/Projections/defaultBehaviour", "useGlobal" )
    #--- 3 Set file name here
    InFlnm=str(x)+'.csv'
    #--- 4  Set pathname here
    InDrPth='C:/your path here'
    #--- 5 Build file name an path for uri
    InFlPth="file:///"+InDrPth+InFlnm
    #---  6 Set import Sting here note only need to set x and y other come for free
    uri = InFlPth+"?delimiter=%s&xField=%s&yField=%s" % (",","long","lat")   
    #--- 7 Load point layer
    bh = QgsVectorLayer(uri, InFlnm, "delimitedtext")
    #--- 8 Confirm something is loaded and valid
    bh.isValid()
    #--- 9 Set CRS
    bh.setCrs(QgsCoordinateReferenceSystem(4326, QgsCoordinateReferenceSystem.EpsgCrsId))
    #--- 10 Display the layer into QGIS (but it asks for CRS before displaying_
    QgsMapLayerRegistry.instance().addMapLayer(bh)
    #--- 11 turn CRS dialog box back on again
    s.setValue( "/Projections/defaultBehaviour", oldValidation )
    #--- 12 load style
    bh.loadNamedStyle(InDrPth+"style.qml")
    bh.triggerRepaint()
    frameLabel.setText(str(x))
    #--- 13 Render and save
    image = c.printPageAsRaster(0)
    image.save(InDrPth+'frame '+str(x)+'.png','png')
    #--- 14 Delete layer
    QgsMapLayerRegistry.instance().removeMapLayers([bh.id()])