"""export.py Export layouts from QGIS project to pdf or jpg. Each exported map will contain a different combination of EP/type, e.g. 0.05/'ZSA' Usage: > export.bat This script must be run with the version of python installed with QGIS, that is why 'export.bat' is required. D Howe d.howe@wrl.unsw.edu.au 2022-05-17 """ import re import os from qgis.core import ( QgsApplication, QgsProject, QgsLayoutExporter, QgsLayoutItemLabel, ) QGZ_PATH = 'roches.qgz' OUTPUT_DIR = 'maps' FORMAT = 'jpg' # Initialise QGIS qgs = QgsApplication([], False) # Load project project = QgsProject.instance() project.read(QGZ_PATH) def unique_attributes(layer): """Get unique values for year, EP, and profile""" layer.setSubsetString('') # Remove filter # Get all available values for encounter probability and profile type eps = [] types = [] years = [] for f in layer.getFeatures(): eps.append(f.attribute('ep')) types.append(f.attribute('type')) years.append(f.attribute('year')) # Keep unique values eps = list(set(eps)) types = list(set(types)) years = list(set(years)) return eps, types, years # Get layers with hazard lines (assuming there is a year in the layer name) map_layers = project.mapLayers().items() layers = [v for k, v in map_layers if re.search(r'\d{4}', v.name())] try: next(layers[0].getFeatures()) except StopIteration: msg = 'No hazard lines found. Check shapefile data.' raise ValueError(msg) # Get all EP values and profile types from first hazard line layer eps, types, years = unique_attributes(layers[0]) # BUG: repeat first file because of QGIS's incorrect legend placement years = [years[0]] + years # Get layouts layouts = project.layoutManager().layouts() # Create outout directory os.makedirs(OUTPUT_DIR, exist_ok=True) for layout in layouts: name = layout.name() # Set up plot settings if FORMAT == 'pdf': settings = QgsLayoutExporter.PdfExportSettings() # settings.dpi = -1 # Native resolution exporter = QgsLayoutExporter(layout).exportToPdf elif FORMAT == 'jpg': settings = QgsLayoutExporter.ImageExportSettings() exporter = QgsLayoutExporter(layout).exportToImage else: raise ValueError("'FORMAT' must be 'jpg' or 'pdf'") for t in types: for e in eps: for layer in layers: year = re.search(r'\d{4}', layer.name()).group() substring = f"ep='{e}' and type='{t}' and year={year}" layer.setSubsetString(substring) # Update label label = f'Type: {t}\nEP: {e}' for item in layout.items(): if isinstance(item, QgsLayoutItemLabel): item.setText(label) map_path = os.path.join(OUTPUT_DIR, f'{name}-{t}-EP={e}.{FORMAT}') print(f'Exporting {os.path.basename(map_path)}...') res = exporter(map_path, settings) if res != 0: msg = 'Export failed. Does output folder exist?' raise ValueError(msg)