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?
-
I do all these things relatively frequently. I have python script which turns csv into shp. I have python script which duplicates qml file (style) for all the shp files in the directory. But usually I load all the layers, make style for first one and then copy paste style to all others in project. And finally I have still unpublished working version of QGIS plugin which loops over all layers in group and export selected composer after every loop as jpg or png and at the end uses ffmpeg to generate video out of images. I will try to get back to your question later when I will have more time.– MiroCommented Jun 6, 2017 at 12:23
-
Ok, to be fair I think this question is really 3 questions in one and very broad. And because of rules here it is going to be most likely closed. I would suggest to break it into sub questions: batch csv import; batch style (if you load all the layers you can copy style from one layer and paste to selection of layers); automatic export of composer for multiple layers (group)– MiroCommented Jun 7, 2017 at 3:04
-
Then for your first question there is already something: gis.stackexchange.com/questions/61664/… and gis.stackexchange.com/questions/68389/… - looking at these question the answer is there is no way without coding yet. I think I have already answered the style batch - in QGIS or whatever tool will copy your qml for all csv/shp files. For the last question I have my own plugin which is still not ready to be published, not sure if there is something else, worth asking...– MiroCommented Jun 7, 2017 at 3:13
-
okay thanks, I'll follow those up! I don't have any background scripting with qgis, so it might take me a while - if/when i get stuck, if this q has been taken down, i'll repost the smaller sub-parts as you suggest :). thanks again for the links!– tzirtziCommented Jun 7, 2017 at 8:04
1 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()])