0

I use QGIS3 and I have project with series of heatmap raster layers from different years (Grass_Snake_2005-2024, one raster layer for each year), in this project I set up already map in map Print Composer. I need to make number of series of maps where I need just change active raster layer in Layer Panel and update year in title in Print Composer.

I write this Python script below, but currently it produce all series with different years but with one still same raster layer, how I can fix that python code that it will be iterate through raster layers and save all series with different raster layers depending to the year of the survey, where is my mistake?

from qgis.core import QgsProject, QgsLayoutExporter, QgsMapLayer
# Function to update print composer title
def update_title(layout, year):
 composer_title = layout.itemById('Title')
 composer_title.setText(f"Distribution of Grass Snakes in the Rhydymwyn Valley, {year}")
# Get the layout
layout = QgsProject.instance().layoutManager().layoutByName('Grass_Snakes')
# Check if layout is found
if layout is None:
 print("Layout 'Grass Snakes' not found.")
 exit()
# Get all raster layers in the project
raster_layers = QgsProject.instance().mapLayers().values()
# Iterate through raster layers and extract years
years = []
for layer in raster_layers:
 if isinstance(layer, QgsMapLayer) and layer.type() == QgsMapLayer.RasterLayer and layer.name().startswith('Grass Snake'):
 year = layer.name().split()[-1] # Extract year from layer name
 years.append(int(year))
# Sort the years in ascending order
years.sort()
# Iterate through years and update print composer title
for year in years:
 # Update print composer title for each year
 update_title(layout, year)
# Export the layout to an image (adjust the file path accordingly)
image_path = f'L:/GIS/Reptiles/Maps/Grass Snake/Logo/Grass_Snake_{year}.jpeg'
exporter = QgsLayoutExporter(layout)
exporter.exportToImage(image_path, QgsLayoutExporter.ImageExportSettings())
print(f"Image exported for year {year}")
PolyGeo
65.5k29 gold badges115 silver badges350 bronze badges
asked Jul 21, 2024 at 2:53

1 Answer 1

1

I see a couple of issues.

Nowhere are you updating the layer in the map item of the layout. So, it continues to display only what is on your current map canvas.

The lines of code at the bottom, that do the exporting, are outside your loop. So they will only work once, for whatever the loop outputs on its last iteration.

I have made some adaptations, namely:

  • sorted the list of raster layers based on their year. This way there is no need to make a separate list of years.
  • performed the validation when making the list of raster layers rather then in the main loop (not strictly necessary but makes the raster_layers variable name more explicit).
  • moved the update_title() call inside the loop
  • set the map item's layers with the current raster layer each loop iteration
  • moved the exporting to image code inside the loop

Note, if you desire more layers than just the distribution raster on your exported image, the other layers will need to be referenced and then added in the map_item.setLayers() call (order is top-bottom).

from qgis.core import QgsProject, QgsLayoutExporter, QgsMapLayer
# Function to update print composer title
def update_title(layout, year):
 composer_title = layout.itemById('Title')
 composer_title.setText(f"Distribution of Grass Snakes in the Rhydymwyn Valley, {year}")
# Get the layout
layout = QgsProject.instance().layoutManager().layoutByName('Grass_Snakes')
# Check if layout is found
if layout is None:
 print("Layout 'Grass Snakes' not found.")
 exit()
# Get the map item in the layout (can also use layout.itemById if you have given it a specific name)
map_item = [x for x in layout.items() if isinstance(x, QgsLayoutItemMap)][0]
# Get all raster layers in the project beginning with 'Grass Snake'
raster_layers = [x for x in QgsProject.instance().mapLayers().values() if isinstance(x, QgsRasterLayer) and layer.name().startswith('Grass Snake')]
# Sort the raster layers based on the year in their name
raster_layers = [x for x in sorted(raster_layers, key=lambda item: int(item.name().split()[-1]))]
# Iterate through raster layers
for layer in raster_layers:
 # Extract year from layer name
 year = layer.name().split()[-1] 
 
 # Update the title
 update_title(layout, year)
 # Pass the layer to the map item
 map_item.setLayers([layer])
 # Export the layout to an image (adjust the file path accordingly)
 image_path = f'L:/GIS/Reptiles/Maps/Grass Snake/Logo/Grass_Snake_{year}.jpeg'
 exporter = QgsLayoutExporter(layout)
 exporter.exportToImage(image_path, QgsLayoutExporter.ImageExportSettings())
 print(f"Image exported for year {year}")
answered Jul 22, 2024 at 9:19

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.