Menghasilkan peta dalam jumlah besar menggunakan PyQGIS?

10

Saya harus membuat sejumlah besar (ratusan) peta distribusi spesies. Saya memiliki shapefile yang berisi distribusi untuk setiap spesies, dan untuk masing-masing, saya ingin mendapatkan peta sebagai gambar (jpg, png atau lainnya) yang berisi nama spesies yang bersangkutan, legenda (untuk membedakan area dari distribusi tahunan, pembibitan, non-pembibitan, dll ...).

Saya ingin menggunakan QGIS untuk melakukan ini.

Satu hari
sumber
1
Bisakah Anda menentukan lebih banyak tentang spesifik peta? Misalnya, apakah Anda ingin semua peta ini menunjukkan area yang sama, seperti benua atau negara tertentu, atau Anda ingin luas peta berubah secara dinamis? Selain itu, apakah Anda ingin semua subtipe rentang pada satu peta atau mereka pada beberapa peta? Bergantung pada jawaban ini, masalah Anda bisa sangat sederhana atau mungkin memerlukan pendekatan yang lebih canggih. Tempat yang baik untuk mulai mencari adalah plugin Atlas untuk GIS, atau jika Anda memiliki ArcGIS 10 atau lebih tinggi, buku peta ESRI juga akan membantu.
Jay Guarneri
1
Maaf atas kekurangan detailnya. Ya untuk semua peta, itu akan menjadi area yang sama (Eropa). Saya punya satu shapefile dengan semua spesies dan, dalam atribut, distribusi yang sesuai. Shapefile ini, saya dapat dengan mudah membaginya dalam shapefile yang berbeda (satu untuk setiap spesies). Pada akhirnya, saya ingin memiliki satu gambar untuk setiap spesies, dengan, pada setiap waktu, area yang persis sama (Eropa), warna yang sama (misalnya distribusi tahunan dalam warna hijau tua, berkembang biak dalam warna hijau muda, non-pembibitan di biru, dll ...), legenda yang sama, dan sebagai judul nama specie.
Onesime
Saya pikir apa yang perlu Anda lakukan adalah merencanakan setiap langkah yang perlu Anda ambil untuk membuat setiap peta, lalu kode pilihan dan memetakan ekspor dengan Python. Saya tahu ini dapat dilakukan dengan mudah di ArcGIS Python, tapi saya tidak cukup tahu tentang antarmuka Python QGIS untuk memberikan banyak panduan. Namun, saya yakin Anda dapat membuat ini bekerja dengan satu shapefile.
Jay Guarneri
Saya telah melakukan sesuatu yang mirip dengan QGIS menggunakan plugin Python. Dalam kasus saya, lapisan saya disimpan di PostGIS, tetapi saya pikir Anda bisa melakukan sesuatu yang serupa menggunakan shapefile. Saya senang membagikan kode saya. PM saya.
Brian Edmond
1
Bisakah Anda mengunggah sampel data Anda untuk kami mainkan.
Nathan W

Jawaban:

4

Saya memiliki persyaratan yang sama dan mengumpulkan plugin QGIS untuk menghasilkan peta, berdasarkan pada shapefile dengan titik lokalitas untuk semua spesies (diasumsikan nama takson yang unik dalam tabel atribut sebagai pengidentifikasi umum). Persyaratan saya tidak serumit - saya tidak memerlukan informasi musiman, judul atau legenda, tetapi ini mungkin merupakan titik awal yang berguna bagi Anda. Untuk aspek yang lebih kompleks, Anda perlu menggunakan komposer peta. Lihat buku resep PyQGIS untuk informasi lebih lanjut tentang itu.

Plugin

Plugin mengotomatiskan pembuatan peta, dan memungkinkan Anda untuk mengonfigurasi luasan, resolusi, dan aspek lainnya. Ini menerapkan gaya yang sama pada output dengan overlay kisi Anda. Saat ini hanya berjalan pada versi pengembangan QGIS (1.9 atau lebih baru).

Skrip sextante

Sebelum saya membuat plugin saya mengerjakan logika menggunakan SEXTANTE. Skrip pengguna ini juga harus berfungsi dalam 1.8 (belum mengujinya). File gaya distribusi (.qml) adalah gaya distribusi output (mengabaikan gaya overlay distribusi). Saat ini ia menempatkan peta output di direktori temp berdasarkan pada standar sistem operasi Anda (/ tmp di Linux, dan berbagai tempat di Windows - ditentukan oleh variabel lingkungan TEMP). Anda dapat dengan mudah mendefinisikan itu sendiri dalam kode. Anda juga perlu mengedit tingkat dan resolusi output dalam kode (dan warna latar belakang jika Anda menginginkan warna yang berbeda untuk laut).

#Definition of inputs and outputs
#==================================
##[Scratch]=group
##all_localities=vector
##taxon_field=field all_localities
##africa_map=vector
##sa_map=vector
##grid_layer=vector
##distribution_style_file=file

#Algorithm body
#==================================
from qgis.core import *
from PyQt4.QtCore import *
from PyQt4.QtGui import *
from sextante.core.QGisLayers import QGisLayers
from sextante.core.SextanteVectorWriter import SextanteVectorWriter
import tempfile
import os

def print_map(taxon,taxon_shp):
    #load taxon layer (necessary?)
    #QGisLayers.load(taxon_shp,name = "taxon",style = distribution_style_file)
    taxon_layer = QgsVectorLayer(taxon_shp,"taxon","ogr")
    QgsMapLayerRegistry.instance().addMapLayer(taxon_layer)
    taxon_layer.loadNamedStyle(distribution_style_file)

    # create image (dimensions 325x299)
    img = QImage(QSize(325,299), QImage.Format_ARGB32_Premultiplied)

    # set image's background color
    color = QColor(192,192,255)   # blue sea
    img.fill(color.rgb())

    # create painter
    p = QPainter()
    p.begin(img)
    p.setRenderHint(QPainter.Antialiasing)

    render = QgsMapRenderer()

    # create layer set
    africa_layer = QGisLayers.getObjectFromUri(africa_map)
    sa_layer = QGisLayers.getObjectFromUri(sa_map)
    #taxon_layer = QGisLayers.getObjectFromUri(taxon_shp)

    lst = []
    lst.append(taxon_layer.id())    
    lst.append(sa_layer.id())
    lst.append(africa_layer.id())

    render.setLayerSet(lst)

    # set extent (xmin,ymin,xmax,ymax)
    rect = QgsRectangle(14.75,-36.00,34.00,-21.00)
    render.setExtent(rect)

    # set output size
    render.setOutputSize(img.size(), img.logicalDpiX())

    # do the rendering
    render.render(p)
    p.end()

    # save image
    #outdir = os.path.dirname(os.path.abspath(output))
    tempdir = tempfile.gettempdir()
    img.save(os.path.join(tempdir,taxon+".png"),"png")

    # remove taxon layer from project
    QgsMapLayerRegistry.instance().removeMapLayers([taxon_layer.id()])

tempdir = tempfile.gettempdir()   
taxa = sextante.runalg('qgis:listuniquevalues', all_localities, taxon_field, None)['UNIQUE_VALUES'].split(";")
for taxon in taxa:
    sextante.runalg('qgis:selectbyattribute', all_localities, taxon_field, 0, taxon)
    sextante.runalg('qgis:selectbylocation', grid_layer, all_localities, 0)
    filename = os.path.join(tempdir,"taxon.shp")    #memory file better?
    sextante.runalg('qgis:saveselectedfeatures', grid_layer, filename)
    print_map(taxon,filename)
rudivonstaden
sumber
Hai semua, Terima kasih atas semua balasan Anda. Untuk memberi Anda beberapa elemen lagi, ini adalah data yang berasal dari BirdLife (contoh untuk specie: birdlife.org/datazone/speciesfactsheet.php?id=2794 ). Secara singkat, ada satu shapefile dengan semua poligon untuk semua spesies (jadi, untuk beberapa dari mereka, banyak garis untuk spesies tunggal), dan ada atribut yang sesuai dengan distribusi musiman (dengan nilai dari 1 hingga 5 sesuai dengan penggunaan yang berbeda ), satu sama lain untuk asal dll. Legenda dan judul tidak diperlukan.
Onesime
- Saya menggunakan layer country di latar belakang, hanya untuk lokasi yang mudah. - Untuk warna yang berbeda untuk nilai yang berbeda dari atribut "musiman", saya pikir untuk itu, penggunaan file .qml cocok. - Secara opsional, untuk judul dan legenda, saya pikir saya harus menggunakan file dari komposer, jika terlalu sulit, saya dapat menambahkannya dengan perangkat lunak lain. - Operasi harus diulang untuk semua spesies, jadi, ini sesuai dengan seleksi berdasarkan atribut, yang akan digunakan untuk memberi nama gambar akhir.
Onesime
Saya mencoba plugin "Atlas", tetapi tampaknya lebih sesuai untuk berbagai lokasi, dalam kasus saya, itu semua waktu untuk area yang sama: Eropa. Saya mencoba plugin "Distribution map manager" yang sepertinya sesuai pada poin ini karena dimungkinkan untuk memperbaiki area jangkauan, tetapi saya tidak memerlukan proses yang memotong titik dengan layer grid karena saya sudah memiliki layer poligon. Saya mencoba di ArcGis, tetapi sama untuk plugin QGis Atlas, solusinya adalah dengan menulis skrip python ...
Onesime
Jadi saya pikir saya akan menggunakan Sextante, berdasarkan pada skrip "rudivonstaden" (terima kasih untuk itu!) Dan untuk menyesuaikannya dengan kasus saya. Akhirnya, Maaf untuk komentar yang berbeda ini, tetapi ada batas nomor karakter ...
Onesime
@Oneime, kecuali untuk judul dan legenda, saya pikir Anda akan dapat mengadaptasi skrip sextante di atas untuk melakukan apa yang Anda butuhkan. Anda mungkin harus menghapus selectbylocationlangkah, dan menambahkan langkah selectbyattributedan tambahan saveselectedfeaturesuntuk setiap musim (ubah grid_layerke all_localities). Kemudian muat lebih banyak file .qml dan tambahkan tambahkan shapefile musiman Anda (lapisan atas ditambahkan terlebih dahulu). Jika Anda tidak yakin bagaimana caranya, saya mungkin dapat mencoba mengedit skrip di atas untuk pekerjaan yang kurang lebih.
rudivonstaden
2

Saya mengambil beberapa waktu untuk mengerjakan ini hari ini. Jadi saya membuat beberapa perubahan pada skrip Anda. Saya tidak perlu menambahkan langkah pilih pilih tambahan dan menyimpan fitur fitur yang dipilih karena saya menggunakan file .qml dan bidang Musiman berada dalam bentuk yang sama. Di bawah, Anda dapat melihat apa yang telah saya lakukan:

#Definition of inputs and outputs
#==================================
##[Scratch]=group
##all_localities=vector
##taxon_field=field all_localities
##seasonal_field=field all_localities
##countries_map=vector
##distribution_style_file=file
##output_folder=folder

#Algorithm body
#==================================
from qgis.core import *
from PyQt4.QtCore import *
from PyQt4.QtGui import *
from sextante.core.QGisLayers import QGisLayers
from sextante.core.SextanteVectorWriter import SextanteVectorWriter
import tempfile
import os

def print_map(taxon,taxon_shp):
#load taxon layer (necessary?)
#QGisLayers.load(taxon_shp,name = "taxon",style = distribution_style_file)
taxon_layer = QgsVectorLayer(taxon_shp,"taxon","ogr")
QgsMapLayerRegistry.instance().addMapLayer(taxon_layer)
taxon_layer.loadNamedStyle(distribution_style_file)

# create image (dimensions 325x299)
img = QImage(QSize(325,299), QImage.Format_ARGB32_Premultiplied)

# set image's background color
color = QColor(221,249,254)   # blue sea
img.fill(color.rgb())

# create painter
p = QPainter()
p.begin(img)
p.setRenderHint(QPainter.Antialiasing)

render = QgsMapRenderer()

# create layer set
countries_layer = QGisLayers.getObjectFromUri(countries_map)
taxon_layer = QGisLayers.getObjectFromUri(taxon_shp)

lst = []
lst.append(taxon_layer.id())    
lst.append(countries_layer.id())
render.setLayerSet(lst)

# set extent (xmin,ymin,xmax,ymax)
rect = QgsRectangle(-11,32,39,71)
render.setExtent(rect)
# set output size
render.setOutputSize(img.size(), img.logicalDpiX())

# do the rendering
render.render(p)
p.end()

#save image
#outdir = os.path.dirname(os.path.abspath(output))
tempdir = output_folder
img.save(os.path.join(tempdir,taxon+".png"),"png")

# remove taxon layer from project
QgsMapLayerRegistry.instance().removeMapLayers([taxon_layer.id()])

tempdir = tempfile.gettempdir()  

taxa = sextante.runalg('qgis:listuniquevalues', all_localities, taxon_field, None)        ['UNIQUE_VALUES'].split(";")

for taxon in taxa:
sextante.runalg('qgis:selectbyattribute', all_localities, taxon_field, 0, taxon)
filename = os.path.join(tempdir,"taxon.shp")    #memory file better?
sextante.runalg('qgis:saveselectedfeatures', all_localities, filename)
print_map(taxon,filename)

Jika Anda memiliki komentar atau saran untuk memperbaikinya, jangan ragu.

Untuk memperbaikinya, yang terbaik adalah ketika kita memilih tingkat (untuk contoh Eropa), ia menggunakan tingkat ini untuk memilih hanya spesies yang termasuk dalam tingkat ini. Ini, karena saya mendapatkan peta untuk semua spesies, bahkan yang di luar Eropa misalnya (jadi saya punya banyak peta kosong). Apakah Anda pikir itu mungkin?

Bersulang,

Satu hari

Satu hari
sumber