How to do a georeferenced Stiff Diagram with Python 3 and QGIS 3 - Tutorial

GeoreferencedStiffDiagram.jpg

Stiff Diagrams are a common and powerful tool for the representation of surface water / groundwater main ions. Anion and cation concentrations are represented on equivalent weight (meq/l), and usually cations are represented at the left side and anions at the right side. Traditionally, this diagram is useful for the comparison of the main water chemical components by examination of a series of diagrams, however it was not easy to compare the diagrams with the position of the observacion point.

To enhance the chemical analysis on regional scale this tutorial has coupled the Stiff Diagrams with their position on a QGIS project. The diagramas are generated from a spreadsheet with Python on a Jupyter Notebook and stored a vector file (.svg), then the images files are referenced on a style file (.sld) and uploaded to QGIS3.

Tutorial


Code

This is the main code for the diagram representation and file export:

Import the required libraries

Fot this tutorial we have developed two packages, one that stores some text for the style file (*.sld) and another that generates the Stiff format. There are required packages for the tutorial as pandas, re, and os.

%matplotlib inline
import pandas as pd
import numpy as np
import re, os

from funciones import *
from variables import *

Define the equivalent concentrations and open the chemistry data

The code converts component concentration to equivalent HCO3 weights and creates a columns with the calculated values for each sample.

#ion dictionary
iones = {
'HCO3': 61, 'CO3' : 30, 'Cl' : 35, 'SO4': 48,
'Na' : 23, 'Ca' : 20, 'Mg' : 12, 'K'  : 39
}

#chemistry dataframe
datosQuimica = pd.read_excel('../InputData/DatosDiagramaStiff.xlsx')

#replace incompatible characters
datosQuimica['Estacion'] = datosQuimica['Estacion'].str.replace("/","_")
datosQuimica['Estacion'] = datosQuimica['Estacion'].str.replace("–","-")
datosQuimica['Estacion'] = datosQuimica['Estacion'].str.replace(" |%/s","")
datosQuimica = datosQuimica.set_index(['Estacion'])

#equivalen weight colum
for ion in iones.keys():
    datosQuimica[str(ion)+'_meq'] = datosQuimica[ion]/iones[ion]

Generation of images files

This tutorial generates the Stiff diagram as Png and SVG files. In order to import the Stiff diagram in QGIS we need the image vector file SVG.

for index, row in datosQuimica.iterrows():
    Na_K, Ca, Mg = row['Na_meq']+row['K_meq'], row['Ca_meq'], row['Mg_meq'] 
    Cl, SO4, HCO3_CO3 = row['Cl_meq'], row['SO4_meq'], row['HCO3_meq']+row['CO3_meq']
    #apply some factor for the axis
    maxConNorm = max([Na_K, Ca, Mg, Cl, SO4, HCO3_CO3])*2
    #set of points of the Stiff diagram
    a = np.array([[0.5 + Cl/maxConNorm,1],[0.5 + SO4/maxConNorm,.5],[0.5 + HCO3_CO3/maxConNorm,0]
                  ,[0.5 - Mg/maxConNorm,0],[0.5 - Ca/maxConNorm,.5],[0.5 - Na_K/maxConNorm,1]])

    figura = diagramaStiff(a, maxConNorm, index)
    figura.savefig('../Svg/Stiff-'+str(index)+'.svg')
    figura.savefig('../Png/Stiff-'+str(index)+'.png')

Representation of the generated Stiff diagrams

A sample representation of the generated diagrams

import matplotlib.pyplot as plt
stiffObject = plt.imread('../Png/Stiff-CHA-01.png')
fig, ax = plt.subplots(figsize=(10,6))
ax.axis('off')
ax.imshow(stiffObject)
plt.show()
Stiff-CHA-01.png

Generation of spatial file and style file

The observation points with their coordinates are exported in one file and the Stiff diagrams are linked on a style file.

#observation point spatial file
datosQuimicaGeo = datosQuimica.loc[:,'Este':'Norte']
datosQuimicaGeo.to_csv('../Txt/datosQuimicaGeo.csv')

#path to the Svg folder
imagePath = os.path.join(os.path.dirname(os.getcwd()),'Svg')
imagePath = imagePath.replace('\\','/')
imagePath

'C:/Users/GIDAWK1/Documents/GeoreferencedStiffDiagramwithPythonandQGIS/Svg'

#style file generation
archivoestilos = open('../Txt/estilosQuimicaGeo.sld','w')
archivoestilos.write(encabezado)

for index, row in datosQuimica.iterrows():
    item = re.sub('%%path%%',imagePath,item)
    estiloitem = re.sub('%%index%%',index,item)
    archivoestilos.write(estiloitem)
archivoestilos.write(final)

archivoestilos.close()

Input files

Input files for this tutorial can be downloaded from this link.




2 Comments

Saul Montoya

Saul Montoya es Ingeniero Civil graduado de la Pontificia Universidad Católica del Perú en Lima con estudios de postgrado en Manejo e Ingeniería de Recursos Hídricos (Programa WAREM) de la Universidad de Stuttgart con mención en Ingeniería de Aguas Subterráneas y Hidroinformática.

Smiley face

Subscribe to our free e-newsletter for tutorials, articles, webminars, courses and more.