2

Initially I have read a csv sheet of atmospheric parameters of 300x300 array of spatial points, the sheet contains 8 columns and 900 rows of data which is read into a numpy like array format using pandas library named as 'pd' in the program. Aim : To create a 300x300 'point' vector layer and assign the values in each row in the csv sheet to the attribute table of the point vector layer so that at the end each point has its respective atmospheric parameter as attribute

Below are the excerpts of my code: I didn't include vector layer creation related lines..

from osgeo import ogr
import processing 
import numpy as np
from numpy import meshgrid
from qgis.core import QgsVectorLayer, QgsField, QgsMapLayerRegistry  
from PyQt4.QtCore import QVariant  
import sys,os
from qgis.core import *
import qgis.utils
from PyQt4.QtGui import *
import processing
import pandas as pd

#Skipped the lines of vector layer creation and those of display onto QGIScanvas
""" Read data from  csv sheet"""

met_csv=r"path/to/the/csvsheet/atmosphericparameters.csv"
df=pd.read_csv(met_csv,sep=',')
Receivers=df.values  #Receivers is a numpy array of the csv sheet

"""append points to the vector layer on the canvas"""

vectlayer_canvas.startEditing()
vpr=vectlayer_canvas.dataProvider()
vpr.addAttributes( [ QgsField("X", QVariant.Int), QgsField("Y", QVariant.Int), QgsField("Data",  QVariant.Double), QgsField("Special",  QVariant.Int), QgsField("VectorX",  QVariant.Double), QgsField("VectorY",  QVariant.Double), QgsField("Symbol",  QVariant.Double), QgsField("S.No.",  QVariant.Int)] )
# nx - no. of columns in the point vector grid, ny- no. of rows
vectlayer_canvas.updateFields()
for i in range(nx):
    for j in range(ny):
       pnt = QgsGeometry.fromPoint(QgsPoint(xv[i][0],yv[0][ny-j-1]))  #assign  the points starting from top-left corner
       feature = QgsFeature()
       feature.setGeometry(pnt)
       vpr.addFeatures([feature])
       vectlayer_canvas.updateExtents()

vectlayer_canvas.commitChanges()

#Until now everything runs as expected i.e., Attribute row has been created..

 """set Attributes"""  
vectlayer_canvas.startEditing()
vpr=vectlayer_canvas.dataProvider()

p=0;q=(ny-1) # Enumeration related aspects: In the csv sheet the values are given starting from (0,29) #then (1,29) ...(29,29) and then (0,28),(1,28)..(29,28).. till (0,0),..,(29,0)

for i in range(len(Receivers)): 

  # add a feature
  feature = QgsFeature()
  print (p,q)
  X = xv[p][0]
  Y = yv[0][q]
  feature.setGeometry( QgsGeometry.fromPoint(QgsPoint(X,Y)) )
  if p==(nx-1): #when p reaches the maximum limit then reset p=0 and   #decrement q, q=q-1
    q-=1;p=0
  else:
    p+=1
  count+=1
 #values=(X,Y,Data,Special,Vector X, Vector Y,Symbol,S.No)
 values = [ QVariant(Receivers[i][0]), QVariant(Receivers[i][1]), QVariant(Receivers[i][2]), QVariant(Receivers[i][3]), QVariant(Receivers[i][4]), QVariant(Receivers[i][5]), QVariant(Receivers[i][6]), QVariant(Receivers[i][7])]
 feature.setAttributes(values)
 vpr.addFeatures([feature])

vectlayer_canvas.commitChanges()

THE ERROR: I am facing with below error while the running the line containing [QVariant(Receivers[i][0]),..]

TypeError: PyQt4.QtCore.QVariant represents a mapped type and cannot be instantiated. The rows or fields corresponding to the Attributes are not getting successfully added ..

Reference: How can I programatically create and add features to a memory layer in QGIS 1.9?

*****After making suggested changes in the second 'for' loop*****

for i in range(len(Receivers)):

  # add a feature
  #  feature = QgsFeature(vectlayer_canvas.fields())
  feature = QgsFeature(vectlayer_canvas.pendingFields())
  print (p,q)
  X = xv[p][0]
  Y = yv[0][q]
  feature.setGeometry( QgsGeometry.fromPoint(QgsPoint(X,Y)) )
  if p==(nx-1): #when p reaches the maximum limit then reset p=0 and decrement q, q=q-1
   q-=1;p=0;qcount+=1;print i
  else:
   p+=1
  count+=1
  fid=i+1 #variable to access the fields/rows of the attribute table
  #values=(X,Y,Data,Special,Vector X, Vector Y,Symbol,S.No)
  #  values = [int(Receivers[i][0]), int(Receivers[i][1]), Receivers[i][2], Receivers[i][3], Receivers[i][4], Receivers[i][5], Receivers[i][6], Receivers[i][7]]
  #  feature.setAttributes(values)
  vpr.addFeatures([feature])
 # attrs = {0: Receivers[i][0],1: Receivers[i][1], 2: Receivers[i][2], 3: Receivers[i][3], 4: Receivers[i][4], 5: Receivers[i][5], 6: Receivers[i][6], 7: Receivers[i][7]}
  #After forcing the datatypes to match datatype of respective fields.
  attrs = {0: int(Receivers[i][0]),1: int(Receivers[i][1]), 2: float(Receivers[i][2]), 3: float(Receivers[i][3]), 4: int(Receivers[i][4]), 5: float(Receivers[i][5]), 6: float(Receivers[i][6]), 7: int(Receivers[i][7])}      
  vpr.changeAttributeValues({ fid : attrs })
#  vpr.addFeatures([feature]) #Shifted up(based on Kuhn's suggestion) so that it is above vpr. changeAttributeValues()

vectlayer_canvas.commitChanges()

Reference : http://docs.qgis.org/testing/en/docs/pyqgis_developer_cookbook/vector.html#modifying-vector-layers

Setback faced: The 'values' are not getting updated in the attribute table of the vector layer...

*****After Modifications based on guidelines in Memory Provider-- The code that works*****

"""append points"""

vpr=vectorLyr.dataProvider()

vpr.addAttributes([ QgsField("X", QVariant.Int), QgsField("Y", QVariant.Int), QgsField("Data",  QVariant.Double), QgsField("Special",  QVariant.Int), QgsField("VectorX",  QVariant.Double), QgsField("VectorY",  QVariant.Double), QgsField("Symbol",  QVariant.Double), QgsField("S.No.",  QVariant.Int)] )
vectorLyr.updateFields()
vectorLyr.isValid()

index=0
for j in range(ny):
    for i in range(nx):
        feature = QgsFeature()
        pnt = QgsGeometry.fromPoint(QgsPoint(xv[i][0],yv[0][ny-j-1]))  #assign  the points starting from top-left corner
        feature.setGeometry(pnt)
        values = [int(Receivers[index][0]), int(Receivers[index][1]), float(Receivers[index][2]), int(Receivers[index][3]), float(Receivers[index][4]), float(Receivers[index][5]), float(Receivers[index][6]), int(Receivers[index][7])]
        index+=1 #increment index to go to next feature
        feature.setAttributes(values)
        vpr.addFeatures([feature])
        vectorLyr.updateExtents()

The above code adds sets the feature values in the attribute table while setting the geometry of the points itself rather than using second 'for' loop for changing the 'NULL' values as it is the case in my previous code. Also in the above code, datatype of the 'Receivers[][]' is forced to match the datatype expected by the Fields in attribute table.

Final note on my observations: The reason for why the second 'for' loop with 'vpr.changeAttributeValues({ fid : attrs })' doesn't work is still not clear for me.. Waiting for suggestions...

2

The code above was written for QGIS 1.x which is out of date for a long time already.

There is a guide available that outlines the major changes in the QGIS API between versions 1 and 2.

Your problem here is related to QVariant which was handled differently in the old days. QGIS 2 converts values implicitly as required.

So just remove the conversion:

values = [ Receivers[i][0], Receivers[i][1],Receivers[i][2], Receivers[i][3], Receivers[i][4], Receivers[i][5], Receivers[i][6], Receivers[i][7]]

Another problem is, that the feature is not properly initialized with the fields.

Have a look to the pyqgis developer cookbook for instructions how to do that :

feature = QgsFeature(vectlayer_canvas.fields())
  • Right now after making the correction, although the program is running without any error, the fields are not getting added on to the Attribute table of the point vector layer i.e., Attribute table has got the heading fields (atmospheric parameters' names, 'X',Y','Data',..) added but their respective values i.e., Receivers[][], are not added... I am unable to figure out the reason.... – Sai Krishna Sep 28 '16 at 5:43
  • I find the information in the pyggis link quite useful. Thank u! – Sai Krishna Sep 28 '16 at 9:07
  • I improvised the code by including the Modify Features commands (updates shown in my code above). But apparently, the fields are not getting updated with the values....! – Sai Krishna Sep 28 '16 at 12:41
  • 1. Attributes can only be changed in the provider after adding the feature. Before adding you have to set them directly on the feature. 2. Calculating feature ids (fid) yourself is very brittle. Only use feature ids which you got from the layer. – Matthias Kuhn Sep 28 '16 at 12:45
  • Do u suggest me to go for previous syntax i.e., 'values = [Receivers[i][0],....]' , then 'feature.setAttributes(values)' and then 'vpr.addFeatures([feature])'. – Sai Krishna Sep 28 '16 at 18:10

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.