# -*- coding: utf-8 -*-
"""
/***************************************************************************
 SUEWSPrepareDatabase
                                 A QGIS plugin
 Prepares inputdata for the SUEWS model using typology database
 Generated by Plugin Builder: http://g-sherman.github.io/Qgis-Plugin-Builder/
                              -------------------
        begin                : 2022-03-22
        git sha              : $Format:%H$
        copyright            : (C) 2022 by Fredrik Lindberg, Oskar Bäcklin
        email                : fredrikl@gvc.gu.se
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 ***************************************************************************/
"""

from qgis.PyQt.QtCore import QSettings, QTranslator, QCoreApplication
from qgis.PyQt.QtGui import QIcon
from qgis.PyQt.QtWidgets import  QAction, QMessageBox, QFileDialog

from qgis.utils import iface
from qgis.core import Qgis

from qgis.core import (QgsMapLayerProxyModel, 
                       QgsFieldProxyModel, 
                       QgsVectorLayer, 
                       QgsFeature, 
                       QgsProject,
                       QgsVectorFileWriter,
                       QgsFeatureRequest)

# Initialize Qt resources from file resources.py
from .resources import *
# Import the code for the dialog
from .suews_prepare_database_dialog import SUEWSPrepareDatabaseDialog
import os.path
# from .tabs.main_tab import MainTab
import webbrowser

#These are not needed here later
import copy
# import time
import numpy as np
import pandas as pd
import os
import yaml

from osgeo import gdal, osr
#from .Utilities import f90nml
from .Utilities import RoughnessCalcFunction as rg
from .Utilities.misc import saveraster
# from .Utilities import wallalgorithms as wa
from .Utilities.db_functions import * 
#from .Utilities.def_config_suews import *

from .Utilities.ssParms import getVertheights, ss_calc_gridlayout
from .Utilities.umep_suewsss_export_component import writeGridLayout
from shutil import copyfile, rmtree

# from .prepare_workertypo import Worker
import processing

################################################################
class SUEWSPrepareDatabase(object):
    """QGIS Plugin Implementation."""

    def __init__(self, iface):
        """Constructor.

        :param iface: An interface instance that will be passed to this class
            which provides the hook by which you can manipulate the QGIS
            application at run time.
        :type iface: QgsInterface
        """
        # Save reference to the QGIS interface
        self.iface = iface
        # initialize plugin directory
        self.plugin_dir = os.path.dirname(__file__)
        # initialize locale
        locale = QSettings().value('locale/userLocale')[0:2]
        locale_path = os.path.join(
            self.plugin_dir,
            'i18n',
            'SUEWSPrepareDatabase_{}.qm'.format(locale))

        if os.path.exists(locale_path):
            self.translator = QTranslator()
            self.translator.load(locale_path)
            QCoreApplication.installTranslator(self.translator)

        self.layerComboManagerPolygrid = None
        self.layerComboManagerPolyField = None
        self.fieldgen = None
        self.LCF_Paved = None
        self.LCF_Buildings = None
        self.LCF_Evergreen = None
        self.LCF_Decidious = None
        self.LCF_Grass = None
        self.LCF_Baresoil = None
        self.LCF_Water = None
        self.pop_density = None
        self.pop_density_day = None
        self.IMP_mean_height = None
        self.IMP_z0 = None
        self.IMP_zd = None
        self.IMP_fai = None
        self.IMPveg_mean_height_dec = None
        self.IMPveg_mean_height_eve = None
        self.IMPveg_fai_dec = None
        self.IMPveg_fai_eve = None
        self.checkBox_twovegfiles = None
        self.IMPvegfile_path_dec = None
        self.IMPvegfile_path_eve = None
        # self.wall_area = None
        self.daypop = 0
        self.typologies = 0
        self.start_DLS = 85
        self.end_DLS = 302
        self.day_since_rain = 0
        self.leaf_cycle = 1
        self.soil_moisture = 100
        self.utc = 1
        self.file_code = ''
        self.steps = 0
        # self.region = None
        self.defTypo = None

        self.output_dir = None
        self.LCFfile_path = None
        self.IMPfile_path = None
        self.IMPvegfile_path = None
        self.Metfile_path = None
        self.LCF_from_file = True
        self.IMP_from_file = True
        self.IMPveg_from_file = True

        self.spartacus = 0
        self.vertheights = '10, 20'
        self.nlayers = 3
        self.skew = 2
        self.heightMethod = 0

        self.LCF_from_file = True
        self.IMP_from_file = True
        self.IMPveg_from_file = True

        # self.comboBoxRegion = True
        self.comboBoxCountry = True
        self.comboBoxPaved = True
        self.comboBoxBareSoil = True
        self.comboBoxBuilding = True
        self.comboBoxGrass = True
        self.comboBoxEvrTree = True
        self.comboBoxDecTree = True
        # self.lclayer = None

        
    def tr(self, message):
        return QCoreApplication.translate('SUEWSPrepareDatabase', message)


    def initGui(self):
        # """Create the menu entries and toolbar icons inside the QGIS GUI."""

        # icon_path = ':/plugins/suews_prepare_database/icon.png'
        # self.add_action(
        #     icon_path,
        #     text=self.tr(u'SUEWS Prepare - Database Typologies'),
        #     callback=self.run,
        #     parent=self.iface.mainWindow())
        
        # Create action that will start plugin configuration
        self.action = QAction(
            QIcon(':/plugins/suews_prepare_database/icon.png'),
            'SUEWS Prepare - Database Typologies', self.iface.mainWindow())
        # connect the action to the run method
        self.action.triggered.connect(self.run)

        # Add toolbar button and menu item
        self.iface.addToolBarIcon(self.action)
        self.iface.addPluginToMenu(self.tr("&SUEWS Prepare - Database Typologies"), self.action)


    def unload(self):
        """Removes the plugin menu item and icon from QGIS GUI."""
        # for action in self.actions:
        #     self.iface.removePluginMenu(
        #         self.tr(u'&SUEWS Prepare - Database Typologies'),
        #         action)
        #     self.iface.removeToolBarIcon(action)

        self.iface.removePluginMenu("&SUEWS Prepare - Database Typologies", self.action)
        self.iface.removeToolBarIcon(self.action)


    def run(self):

        settings_dict = {}

        # Declare instance attributes
        self.dlg = SUEWSPrepareDatabaseDialog()
        self.actions = []
        self.menu = self.tr(u'&SUEWS Prepare (Database Typologies)')
        self.dlg.helpButton.clicked.connect(self.help)

        self.dlg.outputButton.clicked.connect(self.set_output_folder)
        self.dlg.runButton.clicked.connect(self.generate)

        self.outputDialog = QFileDialog()
        self.outputDialog.setFileMode(QFileDialog.Directory)
        self.outputDialog.setOption(QFileDialog.ShowDirsOnly, True)

        self.SSDialog = QFileDialog()
        self.SSDialog.setFileMode(QFileDialog.Directory)
        self.SSDialog.setOption(QFileDialog.ShowDirsOnly, True)

        self.fileDialog = QFileDialog()
        self.fileDialog.setFileMode(QFileDialog.ExistingFile)

        self.fileDialogISO = QFileDialog()
        self.fileDialogISO.setNameFilter("(*_isotropic.txt)")
        self.fileDialogISO.setFileMode(QFileDialog.ExistingFile)

        # Read Database
        self.db_path = self.plugin_dir.split('suews_prepare_database')[0] + 'suews_database_manager/data/database.xlsx'  
        db_dict = read_DB(self.db_path)

        # Filling comboboxes in frame for Regional Parameters
        # 'nameOrigin' is a column created in read_DB to have a readable and understandable indexer shown to the user instead of using the ID
        # The lists here are the ones populating comboboxes for regional parameters
        building_list = db_dict['NonVeg']['nameOrigin'].loc[db_dict['NonVeg']['Surface'] == 'Buildings']
        paved_list =    db_dict['NonVeg']['nameOrigin'].loc[db_dict['NonVeg']['Surface'] == 'Paved']
        bsoil_list =    db_dict['NonVeg']['nameOrigin'].loc[db_dict['NonVeg']['Surface'] == 'Bare Soil']
        grass_list =    db_dict['Veg']['nameOrigin'].loc[db_dict['Veg']['Surface'] == 'Grass']
        dec_tree_list = db_dict['Veg']['nameOrigin'].loc[db_dict['Veg']['Surface'] == 'Deciduous Tree']
        evr_tree_list = db_dict['Veg']['nameOrigin'].loc[db_dict['Veg']['Surface'] == 'Evergreen Tree']
        anthro_list = db_dict['AnthropogenicEmission']['nameOrigin'] #steg1
        traffic_listWD = db_dict['Profiles']['nameOrigin'].loc[db_dict['Profiles']['Profile Type'] == 'Traffic'].loc[db_dict['Profiles']['Day'] == 'Weekday']
        traffic_listWE = db_dict['Profiles']['nameOrigin'].loc[db_dict['Profiles']['Profile Type'] == 'Traffic'].loc[db_dict['Profiles']['Day'] == 'Weekend']
        human_listWD = db_dict['Profiles']['nameOrigin'].loc[db_dict['Profiles']['Profile Type'] == 'Human activity'].loc[db_dict['Profiles']['Day'] == 'Weekday']
        human_listWE = db_dict['Profiles']['nameOrigin'].loc[db_dict['Profiles']['Profile Type'] == 'Human activity'].loc[db_dict['Profiles']['Day'] == 'Weekend']
        popdens_listWD = db_dict['Profiles']['nameOrigin'].loc[db_dict['Profiles']['Profile Type'] == 'Population density'].loc[db_dict['Profiles']['Day'] == 'Weekday']
        popdens_listWE = db_dict['Profiles']['nameOrigin'].loc[db_dict['Profiles']['Profile Type'] == 'Population density'].loc[db_dict['Profiles']['Day'] == 'Weekend']
        energy_listWD = db_dict['Profiles']['nameOrigin'].loc[db_dict['Profiles']['Profile Type'] == 'Energy use'].loc[db_dict['Profiles']['Day'] == 'Weekday']
        energy_listWE = db_dict['Profiles']['nameOrigin'].loc[db_dict['Profiles']['Profile Type'] == 'Energy use'].loc[db_dict['Profiles']['Day'] == 'Weekend']
        snow_listWD = db_dict['Profiles']['nameOrigin'].loc[db_dict['Profiles']['Profile Type'] == 'Snow removal'].loc[db_dict['Profiles']['Day'] == 'Weekday']
        snow_listWE = db_dict['Profiles']['nameOrigin'].loc[db_dict['Profiles']['Profile Type'] == 'Snow removal'].loc[db_dict['Profiles']['Day'] == 'Weekend']
        wateruse_listWD = db_dict['Profiles']['nameOrigin'].loc[db_dict['Profiles']['Profile Type'] == 'Water use (manual)'].loc[db_dict['Profiles']['Day'] == 'Weekday']
        wateruse_listWE = db_dict['Profiles']['nameOrigin'].loc[db_dict['Profiles']['Profile Type'] == 'Water use (manual)'].loc[db_dict['Profiles']['Day'] == 'Weekend']
        
        wateruse_listAWD = db_dict['Profiles']['nameOrigin'].loc[db_dict['Profiles']['Profile Type'] == 'Water use (automatic)'].loc[db_dict['Profiles']['Day'] == 'Weekday']
        wateruse_listAWE = db_dict['Profiles']['nameOrigin'].loc[db_dict['Profiles']['Profile Type'] == 'Water use (automatic)'].loc[db_dict['Profiles']['Day'] == 'Weekend']

        self.dlg.comboBoxPaved.addItems(sorted(paved_list))
        self.dlg.comboBoxBuilding.addItems(sorted(building_list))
        self.dlg.comboBoxBareSoil.addItems(sorted(bsoil_list))
        self.dlg.comboBoxGrass.addItems(sorted(grass_list))
        self.dlg.comboBoxEvrTree.addItems(sorted(evr_tree_list))
        self.dlg.comboBoxDecTree.addItems(sorted(dec_tree_list))
        self.dlg.comboBoxAnthro.addItems(sorted(anthro_list)) 
        self.dlg.comboBoxTrafficWD.addItems(sorted(traffic_listWD))
        self.dlg.comboBoxTrafficWE.addItems(sorted(traffic_listWE))
        self.dlg.comboBoxEnergyUseWD.addItems(sorted(energy_listWD))
        self.dlg.comboBoxEnergyUseWE.addItems(sorted(energy_listWE))
        self.dlg.comboBoxPopdensWD.addItems(sorted(popdens_listWD))
        self.dlg.comboBoxPopdensWE.addItems(sorted(popdens_listWE))
        self.dlg.comboBoxHumanWD.addItems(sorted(human_listWD))
        self.dlg.comboBoxHumanWE.addItems(sorted(human_listWE))
        self.dlg.comboBoxSnowWD.addItems(sorted(snow_listWD))
        self.dlg.comboBoxSnowWE.addItems(sorted(snow_listWE))
        self.dlg.comboBoxIrrigationWD.addItems(sorted(wateruse_listWD)) 
        self.dlg.comboBoxIrrigationWE.addItems(sorted(wateruse_listWE))
        self.dlg.comboBoxIrrigationAWD.addItems(sorted(wateruse_listAWD)) 
        self.dlg.comboBoxIrrigationAWE.addItems(sorted(wateruse_listAWE))
        

        for cbox in [self.dlg.comboBoxPaved, self.dlg.comboBoxBuilding, self.dlg.comboBoxBareSoil, self.dlg.comboBoxEvrTree, self.dlg.comboBoxDecTree, 
                     self.dlg.comboBoxGrass, self.dlg.comboBoxAnthro,self.dlg.comboBoxTrafficWD,self.dlg.comboBoxTrafficWE,
                     self.dlg.comboBoxSnowWD,self.dlg.comboBoxSnowWE,self.dlg.comboBoxHumanWD, self.dlg.comboBoxHumanWE,
                     self.dlg.comboBoxPopdensWD, self.dlg.comboBoxPopdensWE, self.dlg.comboBoxEnergyUseWD, self.dlg.comboBoxEnergyUseWE,
                     self.dlg.comboBoxIrrigationAWD,self.dlg.comboBoxIrrigationAWE, self.dlg.comboBoxIrrigationWD, self.dlg.comboBoxIrrigationWE
                     ]: #steg3
            cbox.setCurrentIndex(-1)

        self.dlg.comboBoxCountry.addItems(sorted(set(list(db_dict['Country']['nameOrigin']))))
        self.dlg.comboBoxCountry.setCurrentIndex(-1)
        
        self.dlg.comboBoxCountry.currentIndexChanged.connect(lambda: self.country_changed(db_dict))

        self.dlg.checkBoxTypology.stateChanged.connect(lambda: self.use_typologies())
        self.dlg.checkBox_day.stateChanged.connect(lambda: self.popdaystate())
        self.dlg.pop_density.currentIndexChanged.connect(lambda: self.set_pop_density())
        self.dlg.pop_density_day.currentIndexChanged.connect(lambda: self.set_pop_density_day())

        self.dlg.layerComboManagerPolygrid.setCurrentIndex(-1)
        self.dlg.layerComboManagerPolygrid.setFilters(QgsMapLayerProxyModel.PolygonLayer)
        self.dlg.layerComboManagerPolygrid.setFixedWidth(175)
        self.dlg.layerComboManagerPolyField.setFilters(QgsFieldProxyModel.LongLong)
        self.dlg.layerComboManagerPolygrid.layerChanged.connect(self.dlg.layerComboManagerPolyField.setLayer)

        # New for Typology database
        self.dlg.layerComboManagerDSM.setFilters(QgsMapLayerProxyModel.RasterLayer)
        self.dlg.layerComboManagerDSM.setFixedWidth(175)
        self.dlg.layerComboManagerDSM.setCurrentIndex(1)
        self.dlg.layerComboManagerDEM.setFilters(QgsMapLayerProxyModel.RasterLayer)
        self.dlg.layerComboManagerDEM.setFixedWidth(175)
        self.dlg.layerComboManagerDEM.setCurrentIndex(0)

        self.dlg.layerComboManagerPolygridTypo.setFilters(QgsMapLayerProxyModel.PolygonLayer)
        self.dlg.layerComboManagerPolygridTypo.setFixedWidth(175)
        self.dlg.layerComboManagerPolygridTypo.setCurrentIndex(-1)

        self.dlg.pop_density.setFilters(QgsFieldProxyModel.Numeric)
        self.dlg.layerComboManagerPolygrid.layerChanged.connect(self.dlg.pop_density.setLayer)

        self.dlg.pop_density_day.setFilters(QgsFieldProxyModel.Numeric)
        self.dlg.layerComboManagerPolygrid.layerChanged.connect(self.dlg.pop_density_day.setLayer)
    
        self.dlg.pushButtonImportLCF.clicked.connect(lambda: self.set_LCFfile_path())
        self.dlg.pushButtonImportIMPVeg.clicked.connect(lambda: self.set_IMPvegfile_path())

        self.dlg.pushButtonImportIMPVeg_eve.clicked.connect(lambda: self.set_IMPvegfile_path_eve())
        self.dlg.pushButtonImportIMPVeg_dec.clicked.connect(lambda: self.set_IMPvegfile_path_dec())

        self.dlg.pushButtonImportIMPBuild.clicked.connect(lambda: self.set_IMPfile_path())
        self.dlg.pushButtonImportMet.clicked.connect(lambda: self.set_metfile_path())

        self.dlg.spinBoxStartDLS.valueChanged.connect(lambda: self.start_DLS_changed(self.dlg.spinBoxStartDLS.value()))
        self.dlg.spinBoxEndDLS.valueChanged.connect(lambda: self.end_DLS_changed(self.dlg.spinBoxEndDLS.value()))

        self.dlg.spinBoxSoilMoisture.valueChanged.connect(lambda: self.soil_moisture_changed(self.dlg.spinBoxSoilMoisture.value()))
        self.dlg.comboBoxLeafCycle.currentIndexChanged.connect(lambda: self.leaf_cycle_changed(self.dlg.comboBoxLeafCycle.currentIndex()))
        self.dlg.fileCodeLineEdit.textChanged.connect(lambda: self.file_code_changed(self.dlg.fileCodeLineEdit.text()))
        self.dlg.lineEditUTC.textChanged.connect(lambda: self.utc_changed(self.dlg.lineEditUTC.text()))

        #SS related GUI things
        self.dlg.checkBoxSS.stateChanged.connect(lambda: self.use_spartacus())
        self.dlg.SS_comboBox.currentIndexChanged.connect(lambda: self.height_option_SS(self.dlg.SS_comboBox.currentIndex()))
        self.dlg.SS_LineEdit_constant.textChanged.connect(lambda: self.vertHeights_changed(self.dlg.SS_LineEdit_constant.text()))
        self.dlg.spinBoxLayers.valueChanged.connect(lambda: self.layersSS_changed(self.dlg.spinBoxLayers.value()))
        self.dlg.SS_checkBox_skew.stateChanged.connect(lambda: self.SS_skew())
        

        # New for traffic linedata
        self.dlg.layerComboManagerTraffic.setCurrentIndex(-1)
        self.dlg.layerComboManagerTraffic.setFilters(QgsMapLayerProxyModel.LineLayer)
        self.dlg.layerComboManagerTraffic.setFixedWidth(175)
        self.dlg.layerComboManagerTrafficField.setFilters(QgsFieldProxyModel.LongLong)
        self.dlg.layerComboManagerTraffic.layerChanged.connect(self.dlg.layerComboManagerTrafficField.setLayer)
        self.dlg.show()
        self.dlg.adjustSize()
        self.dlg.exec_()

    def help(self):
        url = "https://umep-docs.readthedocs.io/en/latest/pre-processor/Urban%20Energy%20Balance%20SUEWS%20Database%20Manager.html"
        webbrowser.open_new_tab(url)

    def set_output_folder(self):
        self.outputDialog.open()
        result = self.outputDialog.exec_()
        if result == 1:
            self.output_dir = self.outputDialog.selectedFiles()
            self.dlg.textOutput.setText(self.output_dir[0])
            self.dlg.runButton.setEnabled(1)

    def height_option_SS(self, value):
        self.heightMethod = value

    def layersSS_changed(self, value):
        self.nlayers = value

    def vertHeights_changed(self, heights):      
        self.vertheights = heights

    def SS_skew(self):
        if self.dlg.SS_checkBox_skew.isChecked():
            self.skew = 2
        else:
            self.skew = 1

    def soil_moisture_changed(self, value):
        self.soil_moisture = value

    def utc_changed(self, index):
        self.utc = index

    def leaf_cycle_changed(self, index):
        self.leaf_cycle = index

    def file_code_changed(self, code):
        self.file_code = code


    def country_changed(self, db_dict):
        country_sel = self.dlg.comboBoxCountry.currentText()
        reg_sel = db_dict['Country'].loc[db_dict['Country']['nameOrigin'] == country_sel]['Region'].item()
        # reg_sel = self.dlg.comboBoxRegion.currentText()

        self.country_str = country_sel
        self.region_str = reg_sel
        # Update region according to country if country is chosen before region
        self.dlg.lineEditRegInfo.setText(reg_sel)

        # Function to test if a parameter is found in Country. If not, the same parameter for Region is then selected.
            
        def decide_country_region(col, country_sel, reg_sel, comboBox):
            country_df = db_dict['Country'][db_dict['Country']['nameOrigin'] == country_sel]
            
            if str(country_df[col].item()) == 'nan':
                reg_df = db_dict['Region'][db_dict['Region']['Region'] == reg_sel]
                var = reg_df[col].item()
                var_text = db_dict[surf_df_dict[col]].loc[var, 'nameOrigin']
                cbox_list = [comboBox.itemText(i) for i in range(comboBox.count())]
                try:
                    indexer = cbox_list.index(var_text)
                except:
                    comboBox.addItems([var_text])
                    cbox_list = [comboBox.itemText(i) for i in range(comboBox.count())]
                    indexer = cbox_list.index(var_text)

            else:
                var = country_df[col].item()
                var_text = db_dict[surf_df_dict[col]].loc[var, 'nameOrigin']
                cbox_list = [comboBox.itemText(i) for i in range(comboBox.count())]
                try:
                    indexer = cbox_list.index(var_text)
                except:
                    comboBox.addItems([var_text])
                    cbox_list = [comboBox.itemText(i) for i in range(comboBox.count())]
                    indexer = cbox_list.index(var_text)
    
            comboBox.setCurrentIndex(indexer)

        decide_country_region('Paved',country_sel, reg_sel, self.dlg.comboBoxPaved)
        decide_country_region('Buildings', country_sel, reg_sel, self.dlg.comboBoxBuilding)
        decide_country_region('Bare Soil', country_sel, reg_sel, self.dlg.comboBoxBareSoil)
        decide_country_region('Evergreen Tree',country_sel, reg_sel, self.dlg.comboBoxEvrTree)
        decide_country_region('Deciduous Tree',country_sel, reg_sel, self.dlg.comboBoxDecTree)
        decide_country_region('Grass',country_sel, reg_sel, self.dlg.comboBoxGrass)
        decide_country_region('AnthropogenicCode',country_sel, reg_sel, self.dlg.comboBoxAnthro)
        decide_country_region('TraffProfWD',country_sel, reg_sel, self.dlg.comboBoxTrafficWD) #finns bara i country?
        decide_country_region('TraffProfWE',country_sel, reg_sel, self.dlg.comboBoxTrafficWE) 
        decide_country_region('ActivityProfWD',country_sel, reg_sel, self.dlg.comboBoxHumanWD)
        decide_country_region('ActivityProfWE',country_sel, reg_sel, self.dlg.comboBoxHumanWE)
        decide_country_region('PopProfWD',country_sel, reg_sel, self.dlg.comboBoxPopdensWD)
        decide_country_region('PopProfWE',country_sel, reg_sel, self.dlg.comboBoxPopdensWE)
        decide_country_region('EnergyUseProfWD',country_sel, reg_sel, self.dlg.comboBoxEnergyUseWD)
        decide_country_region('EnergyUseProfWE',country_sel, reg_sel, self.dlg.comboBoxEnergyUseWE)
        decide_country_region('WaterUseProfManuWD',country_sel, reg_sel, self.dlg.comboBoxIrrigationWD) #TODO Manual and Auto together?
        decide_country_region('WaterUseProfManuWE',country_sel, reg_sel, self.dlg.comboBoxIrrigationWE)
        decide_country_region('WaterUseProfAutoWD',country_sel, reg_sel, self.dlg.comboBoxIrrigationAWD) #TODO Manual and Auto together?
        decide_country_region('WaterUseProfAutoWE',country_sel, reg_sel, self.dlg.comboBoxIrrigationAWE)
        decide_country_region('SnowClearingProfWD',country_sel, reg_sel, self.dlg.comboBoxSnowWD)
        decide_country_region('SnowClearingProfWE',country_sel, reg_sel, self.dlg.comboBoxSnowWE)

    def use_typologies(self):
        if self.dlg.checkBoxTypology.isChecked():
            self.typologies = 1
        else:
            self.typologies = 0

    def use_spartacus(self):
        if self.dlg.checkBoxSS.isChecked():
            self.spartacus = 1
        else:
            self.spartacus = 0

    def popdaystate(self):
        if self.dlg.checkBox_day.isChecked():
            self.daypop = 1
        else:
            self.daypop = 0

    def set_pop_density(self):
            self.pop_density = self.dlg.pop_density.currentText()
    
    def set_pop_density_day(self):
        self.pop_density_day = self.dlg.pop_density_day.currentText()

    def set_LCFfile_path(self):
        self.fileDialogISO.open()
        result = self.fileDialogISO.exec_()
        if result == 1:
            self.LCFfile_path = self.fileDialogISO.selectedFiles()
            self.dlg.textInputLCFData.setText(self.LCFfile_path[0])
        else:
            self.LCFfile_path = None
            self.dlg.textInputLCFData.setText('')

    def set_IMPfile_path(self):
        self.fileDialogISO.open()
        result = self.fileDialogISO.exec_()
        if result == 1:
            self.IMPfile_path = self.fileDialogISO.selectedFiles()
            self.dlg.textInputIMPData.setText(self.IMPfile_path[0])
            self.ss_dir = os.path.dirname(self.IMPfile_path[0])
            self.dlg.textInputIMPDataSS.setText(self.ss_dir)
        else:
            self.IMPfile_path = None
            self.dlg.textInputIMPData.setText('')

    def set_IMPvegfile_path(self):
        self.fileDialogISO.open()
        result = self.fileDialogISO.exec_()
        if result == 1:
            self.IMPvegfile_path = self.fileDialogISO.selectedFiles()
            self.dlg.textInputIMPVegData.setText(self.IMPvegfile_path[0])
        else:
            self.IMPvegfile_path = None
            self.dlg.textInputIMPVegData.setText('')


    def set_IMPvegfile_path_dec(self):
        self.fileDialogISO.open()
        result = self.fileDialogISO.exec_()
        if result == 1:
            self.IMPvegfile_path_dec = self.fileDialogISO.selectedFiles()
            self.dlg.textInputIMPDecData.setText(self.IMPvegfile_path_dec[0])
        else:
            self.IMPvegfile_path_dec = None
            self.dlg.textInputIMPDecData.setText('')

    def set_IMPvegfile_path_eve(self):
        self.fileDialogISO.open()
        result = self.fileDialogISO.exec_()
        if result == 1:
            self.IMPvegfile_path_eve = self.fileDialogISO.selectedFiles()
            self.dlg.textInputIMPEveData.setText(self.IMPvegfile_path_eve[0])
        else:
            self.IMPvegfile_path_eve = None
            self.dlg.textInputIMPEveData.setText('')

    def set_metfile_path(self):
        self.Metfile_path = self.fileDialog.getOpenFileName()
        self.dlg.textInputMetData.setText(self.Metfile_path[0])


    def start_DLS_changed(self, value):
        self.start_DLS = value


    def end_DLS_changed(self, value):
        self.end_DLS = value


    def generate(self):
        
        # First check that all parts of the interface have been filled in correclty
        # output dir
        if self.output_dir is None:
            QMessageBox.critical(self.dlg, "Error", "No output directory selected")
            return  

        # metfile
        year = None
        year2 = None

        if self.Metfile_path is None:
            QMessageBox.critical(self.dlg, "Error", "Meteorological data file has not been provided")
            return
            pass
        elif os.path.isfile(self.Metfile_path[0]):
            with open(self.Metfile_path[0]) as metfile:
                next(metfile)
                for line in metfile:
                    split = line.split()
                    if year == split[0]:
                        break
                    else:
                        if year2 == split[0]:
                            year = split[0]
                            break
                        elif year is None:
                            year = split[0]
                        else:
                            year2 = split[0]
        else:
            QMessageBox.critical(self.dlg, "Error", "Could not find the file containing meteorological data")
            return
            pass
        

        # # check polygon grid
        poly = self.dlg.layerComboManagerPolygrid.currentLayer()
            
        if poly is None:
           QMessageBox.critical(None, "Error", "No valid Polygon layer is selected")
           return
        

        poly_field = self.dlg.layerComboManagerPolyField.currentField()
        
        if poly_field == '':
            QMessageBox.critical(None, "Error", "An attribute field with unique fields must be selected")
            return

        vlayer = QgsVectorLayer(poly.source(), "polygon", "ogr")

        map_units = vlayer.crs().mapUnits()
        if not map_units == 0 or map_units == 1 or map_units == 2:
            QMessageBox.critical(self.dlg, "Error", "Could not identify the map units of the polygon layer coordinate "
                                 "reference system")
            return

        if self.dlg.pop_density.currentField() == '':
            QMessageBox.critical(None, "Error", "An attribute field including night-time population density (pp/ha) must be selected")
            return


        if self.daypop == 1:
            if self.dlg.pop_density_day.currentField() == '':
                QMessageBox.critical(None, "Error", "An attribute field including working population density (pp/ha) must be selected")
                return    

        # Leaf cycle
        if self.leaf_cycle == 0:
            QMessageBox.critical(self.dlg, "Error", "No leaf cycle period has been selected")
            return
        else:
            if not (self.leaf_cycle == 1 or self.leaf_cycle == 5):
                QMessageBox.critical(self.dlg,"Warning", "A transition period between Winter and Summer has been "
                                     "choosen. Preferably start the model run during Winter or Summer.")

        # Morphometric and land cover files


        if self.IMP_from_file:
            if self.IMPfile_path is None:
                QMessageBox.critical(None, "Error", "Building morphology file has not been provided")
                return
            if not os.path.isfile(self.IMPfile_path[0]):
                QMessageBox.critical(None, "Error", "Could not find the file containing building morphology")
                return
        if self.IMPveg_from_file:
            if self.IMPvegfile_path is None:
                QMessageBox.critical(None, "Error", "Vegetation morphology file has not been provided")
                return
            if not os.path.isfile(self.IMPvegfile_path[0]):
                QMessageBox.critical(None, "Error", "Could not find the file containing vegetation morphology")
                return

        if self.LCF_from_file:
            if self.LCFfile_path is None:
                QMessageBox.critical(None, "Error", "Land cover fractions file has not been provided")
                return
            if not os.path.isfile(self.LCFfile_path[0]):
                QMessageBox.critical(None, "Error", "Could not find the file containing land cover fractions")
                return
        

        if self.file_code == '':
            QMessageBox.critical(None, "Error", "Specify a file code prefix")
            return

        # # DSM layer for aggegation
        dsmlayer = self.dlg.layerComboManagerDSM.currentLayer()
        if dsmlayer is None:
            QMessageBox.critical(self.dlg, "Error", "No valid ground and building DSM is selected")
            return

        demlayer = self.dlg.layerComboManagerDEM.currentLayer()
        if demlayer is None:
            QMessageBox.critical(self.dlg, "Error", "No valid DEM selected")
            return
        
        # cdsmlayer = self.dlg.layerComboManagerCDSM.currentLayer()
        # if cdsmlayer is None:
        #     QMessageBox.critical(self.dlg, "Error", "No valid vegetation DSM (CDSM) selected")
        #     return

        # # # Land cover layer for aggegation
        # lclayer = self.dlg.layerComboManagerLC.currentLayer()
        # if lclayer is None:
        #     QMessageBox.critical(self.dlg, "Error", "No valid land cover grid is selected")
        #     return   

        polyTypolayer = self.dlg.layerComboManagerPolygridTypo.currentLayer()
        if self.typologies == 1 and polyTypolayer is None:
            QMessageBox.critical(None, "Error", "No valid Urban typology polygon layer is selected")
            return   
        
        # typologyFieldName = self.dlg.layerComboManagerPolygridTypofield.currentText()
        typologyFieldName = 'TypolID'

        # Spartacus check
        if self.spartacus == 1:
            if self.heightMethod == 0:
                QMessageBox.critical(self.dlg, "Error", "No method to set height intervals is specified")
                return
            elif self.heightMethod == 1:
                try:
                    listtext = self.vertheights.split(',')
                    listtext.insert(0, '0.0')
                    floats = [float(x) for x in listtext]
                except:
                    QMessageBox.critical(self.dlg, "Error", "One or more inputs in Fixed height [option 1] is non-numeric. "
                                        "Remember to use comma between numbers")
                    return
                start = -1.0
                self.vertheights = []
                for x in floats:
                    if x > start:
                        self.vertheights.append(x)
                        start = x
                    else:
                        QMessageBox.critical(self.dlg, "Error", "One or more inputs in Fixed height [option 1] is not increasing.")
                        return

        settings_dict = {
            
            'vlayer':vlayer, 'poly_field':poly_field, 'Metfile_path': self.Metfile_path, 'start_DLS': self.start_DLS, 
            'end_DLS': self.end_DLS, 'LCF_from_file' :self.LCF_from_file, 'LCFfile_path' : self.LCFfile_path, 'plugin_dir': self.plugin_dir, 'map_units': map_units, 
            'output_dir': self.output_dir, 'file_code' :self.file_code, 'utc':self.utc,
            'IMP_from_file' : self.IMP_from_file, 'IMPfile_path': self.IMPfile_path, 'IMP_z0' : self.IMP_z0, 'IMP_zd' : self.IMP_zd, 
            'IMP_fai': self.IMP_fai, 'IMPveg_from_file': self.IMPveg_from_file, 'IMPvegfile_path': self.IMPvegfile_path, 
            'IMPveg_fai_eve': self.IMPveg_fai_eve, 'IMPveg_fai_dec' : self.IMPveg_fai_dec, 'pop_density' : self.pop_density, 
             'checkBox_twovegfiles' : self.checkBox_twovegfiles, 'IMPvegfile_path_dec':  self.IMPvegfile_path_dec, 
            # Typology
            'IMPvegfile_path_eve' : self.IMPvegfile_path_eve, 'pop_density_day': self.pop_density_day, 'daypop' :self.daypop,
            'polyTypolayer' : polyTypolayer, 'typologyFieldName': typologyFieldName, 'dsmlayer': dsmlayer, 'demlayer' :demlayer, 
            'region_str' : self.region_str, 'country_str' : self.country_str, 'checkBoxTypologies' :self.typologies,                          
            # Spartacus 
            'heightMethod' : self.heightMethod,  'vertheights' : self.vertheights, 'nlayers' : self.nlayers, 
            'skew' : self.skew, 'ss_dir': self.ss_dir, 'spartacus': self.spartacus, 
            }

        # Add to settings_dict selected profiles and surfaces
        for cbox, var in zip(
            [self.dlg.comboBoxPaved, self.dlg.comboBoxBuilding,self.dlg.comboBoxBareSoil, self.dlg.comboBoxEvrTree, self.dlg.comboBoxDecTree, 
            self.dlg.comboBoxGrass, self.dlg.comboBoxAnthro,self.dlg.comboBoxTrafficWD,self.dlg.comboBoxTrafficWE,
            self.dlg.comboBoxSnowWD,self.dlg.comboBoxSnowWE,self.dlg.comboBoxHumanWD, self.dlg.comboBoxHumanWE,
            self.dlg.comboBoxPopdensWD, self.dlg.comboBoxPopdensWE, self.dlg.comboBoxEnergyUseWD, self.dlg.comboBoxEnergyUseWE,
            self.dlg.comboBoxIrrigationWD,self.dlg.comboBoxIrrigationWE, self.dlg.comboBoxIrrigationAWD,self.dlg.comboBoxIrrigationAWE],
        
            ['Paved' ,'Buildings', 'Bare Soil', 'Evergreen Tree', 'Deciduous Tree', 
            'Grass' ,'AnthropogenicCode', 'TraffProfWD'  , 'TraffProfWE',
            'SnowClearingProfWD','SnowClearingProfWE', 'ActivityProfWD','ActivityProfWE',
            'PopProfWD' , 'PopProfWE', 'EnergyUseProfWD', 'EnergyUseProfWE',
            'WaterUseProfManuWD', 'WaterUseProfManuWE','WaterUseProfAutoWD', 'WaterUseProfAutoWE']):
            
            settings_dict[var] =  cbox.currentText()
        
        # TODO     
        # #Here worker loop starts. We make function. Then it is easier to put in worker later
        self.generateSiteSelect(settings_dict)

        # OLD EDIT KEEP
        # self.generateSiteSelect(vlayer, poly_field, self.Metfile_path, self.start_DLS, self.end_DLS, self.LCF_from_file, self.LCFfile_path,
        #                  self.IMP_from_file, self.IMPfile_path, self.IMP_z0, self.IMP_zd, self.IMP_fai, self.IMPveg_from_file, self.IMPvegfile_path, 
        #                  self.IMPveg_fai_eve, self.IMPveg_fai_dec, self.pop_density, self.plugin_dir, map_units, self.output_dir, self.file_code,
        #                  self.utc, self.checkBox_twovegfiles, self.IMPvegfile_path_dec, self.IMPvegfile_path_eve, self.pop_density_day, self.daypop,
        #                  polyTypolayer, typologyFieldName, dsmlayer, demlayer, self.region_str, self.country_str, self.typologies,
        #                  self.heightMethod, self.vertheights, self.nlayers, self.skew, self.ss_dir, self.spartacus, self.defTypo)

        # self.startWorker(vlayer, poly_field, self.Metfile_path, self.start_DLS, self.end_DLS, self.LCF_from_file, self.LCFfile_path,
        #                  self.LCF_Paved, self.LCF_Buildings, self.LCF_Evergreen, self.LCF_Decidious, self.LCF_Grass, self.LCF_Baresoil,
        #                  self.LCF_Water, self.IMP_from_file, self.IMPfile_path, self.IMP_mean_height, self.IMP_z0, self.IMP_zd,
        #                  self.IMP_fai, self.IMPveg_from_file, self.IMPvegfile_path, self.IMPveg_mean_height_eve,
        #                  self.IMPveg_mean_height_dec, self.IMPveg_fai_eve, self.IMPveg_fai_dec, self.pop_density, 
        #                  self.plugin_dir, map_units,
        #                  self.output_dir, self.day_since_rain, self.leaf_cycle, self.soil_moisture, self.file_code,
        #                  self.utc, self.checkBox_twovegfiles, self.IMPvegfile_path_dec, self.IMPvegfile_path_eve, self.pop_density_day, self.daypop)
    def generateSiteSelect(self, settings_dict):
    # def generateSiteSelect(self, vlayer, poly_field, Metfile_path, start_DLS, end_DLS, LCF_from_file, LCFfile_path,
    #                      IMP_from_file, IMPfile_path, IMP_z0, IMP_zd, IMP_fai, IMPveg_from_file, IMPvegfile_path, 
    #                      IMPveg_fai_eve, IMPveg_fai_dec, pop_density, plugin_dir, map_units, output_dir, file_code,
    #                      utc, checkBox_twovegfiles, IMPvegfile_path_dec, IMPvegfile_path_eve, pop_density_day, daypop,
    #                      polyTypolayer, typologyFieldName, dsmlayer, demlayer, region_str, country_str, checkBoxTypologies,
    #                      heightMethod, vertheights, nlayerIn, skew, ss_dir, spartacus, defTypo):

        
        plugin_dir = settings_dict['plugin_dir']
        output_dir = settings_dict ['output_dir']

        save_txt_folder = output_dir[0]+ '/'
        temp_folder = plugin_dir + '/tempdata'
        walls_raster_out = temp_folder + '/walls.tif'

        build_raster_out = temp_folder + '/buildings.tif'
        typo_raster_out = temp_folder + '/typoraster.tif'

        # Clean temp folder
        try:
            rmtree(temp_folder)
        except OSError as e:
            print ("Warning: %s - %s." % (e.filename, e.strerror))

        os.mkdir(temp_folder)

        ss_dict = {}                 # SiteSelect Dict. This is the final dict where all parameters for each grid are found. 
        veg_dict = {}                # dict for populating and sorting Veg parameter
        nonVeg_dict = {}             # dict for populating and sorting NonVeg parameter
        country_conv_dict = {}       # Dict for getting selected Country parameters
        parameter_dict = {}          # Unknown TODO Describe
        spartacus_error_dict = {}    # Used to collect potential Spartacus error and present for user
       # Read DB
        db_dict = read_DB(self.db_path)
    
        # change stringnames to codes. bit annoying, but more effective.. 20241127
        gui_lookup_dict = GUI_lookup_dict(db_dict)
        for var, lookup in zip(
            ['Paved' ,'Buildings', 'Bare Soil', 'Evergreen Tree', 'Deciduous Tree', 
            'Grass' ,'AnthropogenicCode', 'TraffProfWD'  , 'TraffProfWE',
            'SnowClearingProfWD','SnowClearingProfWE', 'ActivityProfWD','ActivityProfWE',
            'PopProfWD' , 'PopProfWE', 'EnergyUseProfWD', 'EnergyUseProfWE',
            'WaterUseProfManuWD', 'WaterUseProfManuWE','WaterUseProfAutoWD', 'WaterUseProfAutoWE'],
            
            ['Paved' ,'Buildings', 'Bare Soil', 'Evergreen Tree', 'Deciduous Tree', 
            'Grass' ,'AnthropogenicEmission', 'Traffic'  , 'Traffic',
            'Snow removal','Snow removal', 'Human activity','Human activity',
            'Population density' , 'Population density', 'Energy use', 'Energy use',
            'Water use (manual)', 'Water use (manual)','Water use (automatic)', 'Water use (automatic)']):

            try:
                settings_dict[var] =  gui_lookup_dict[lookup][settings_dict[var]]

            except:
                  for lu in ['Paved' ,'Buildings', 'Bare Soil', 'Evergreen Tree', 'Deciduous Tree', 
                    'Grass' ,'AnthropogenicEmission', 'Traffic'  , 'Traffic',
                    'Snow removal','Snow removal', 'Human activity','Human activity',
                    'Population density' , 'Population density', 'Energy use', 'Energy use',
                    'Water use (manual)', 'Water use (manual)','Water use (automatic)', 'Water use (automatic)']:
                    try:
                        settings_dict[var] =  gui_lookup_dict[lu][settings_dict[var]]
                        break
                    except:
                        pass
        
        # Vectorize country_conv_dict creation
        country_conv_dict = (db_dict['Country']['Country'] + ', ' + db_dict['Country']['City']).to_dict()
        country_conv_dict_inv = {v: k for k, v in country_conv_dict.items()}

        # Get selected country
        country_sel = db_dict['Country'].loc[[country_conv_dict_inv[settings_dict['country_str']]]]

        # Drop irrelevant columns
        column_list = db_dict['Country'].drop(columns=['Region', 'Country', 'City']).columns

        # Set parameters from regional or country level and populate parameter_dict
        parameter_dict = {column: decide_country_or_region(column, country_sel, db_dict['Region']) for column in column_list}

        if settings_dict['LCF_from_file']:
            LCF_dict = read_morph_txt(settings_dict['LCFfile_path'][0])

        if settings_dict['IMP_from_file']:
            IMP_dict = read_morph_txt(settings_dict['IMPfile_path'][0])

        if settings_dict['IMPveg_from_file']:
            IMPveg_dict = read_morph_txt(settings_dict['IMPvegfile_path'][0])

        
        geodata_output = {} # Dict for storing the output of the QGIS geodata processes

        # New approach 20240219. Create typologylayer if no typoloayer exist
        if settings_dict['checkBoxTypologies'] == 0:
            parin = {'INPUT':settings_dict['vlayer'],
                'FIELD':[],
                'SEPARATE_DISJOINT':False,
                'OUTPUT':temp_folder + '/defaultTypo.shp'}
            geodata_output['defaulttypo'] = processing.run("native:dissolve", parin )

            # defaultTypoID = db_dict['NonVeg'].loc[db_dict['NonVeg']['nameOrigin']==defTypo].index.item()
            
            defaultTypoID = create_code('Types')
            db_dict['Types'].loc[defaultTypoID, 'Paved'] = settings_dict['Paved']#db_dict['NonVeg'][(db_dict['NonVeg']['nameOrigin'] == settings_dict['Paved']) & (db_dict['NonVeg']['Surface'] == 'Paved')].index.item()
            db_dict['Types'].loc[defaultTypoID, 'Buildings'] = settings_dict['Buildings']#db_dict['NonVeg'][(db_dict['NonVeg']['nameOrigin'] == settings_dict['Buildings']) & (db_dict['NonVeg']['Surface'] == 'Buildings')].index.item()

            parin = {'INPUT':geodata_output['defaulttypo']['OUTPUT'],
                     'FIELD_NAME':'TypolID',
                     'FIELD_TYPE':1,'FIELD_LENGTH':0,'FIELD_PRECISION':0,
                     'FORMULA': str(defaultTypoID),
                     'OUTPUT':temp_folder + '/defaultTypo2.shp'}

            geodata_output['defaulttypo2'] = processing.run("native:fieldcalculator", parin)

            settings_dict['polyTypolayer'] = QgsVectorLayer(geodata_output['defaulttypo2']['OUTPUT'],'typo','ogr')


        # If using Typologies then aggregation is needed. Otherwise no aggregation will be done TODO: ta bort if??
        #if checkBoxTypologies == 1:
        # DEM & DSM to arrays
        gdal.AllRegister()
        provider = settings_dict['demlayer'].dataProvider()
        filePath_dem = str(provider.dataSourceUri())
        dem = gdal.Open(filePath_dem)
        dem_arr = dem.ReadAsArray().astype(float)

        provider = settings_dict['dsmlayer'].dataProvider()
        filePath_dsm = str(provider.dataSourceUri())
        dsm = gdal.Open(filePath_dsm)
        dsm_arr = dsm.ReadAsArray().astype(float)

        #isolate buildings in dsm to be able to calculate mean height
        build_arr = dsm_arr-dem_arr
        build_arrW  = build_arr.copy()
        build_arr[np.where(build_arr < 0.5)] = np.nan
        saveraster(gdal.Open(filePath_dsm), build_raster_out, build_arr)
        # dsm_arr = None
        # dem_arr = None
        pixelSize = dsm.GetGeoTransform()[1]

        # Grid classified shp-file containing SUEWS typologies
        parin = { 'INPUT' : settings_dict['vlayer'],
            'INPUT_FIELDS' : [], 
            'OUTPUT' : temp_folder + '/urbantypelayer.shp', # 'TEMPORARY_OUTPUT',#urbantypelayer,
            'OVERLAY' : settings_dict['polyTypolayer'], 
            'OVERLAY_FIELDS' : [], 
            'OVERLAY_FIELDS_PREFIX' : '' }
        geodata_output['gridded_shp'] = processing.run('native:intersection', parin)

        # Dissolve on GridID and Typology. 
        parin = {
            'INPUT':geodata_output['gridded_shp']['OUTPUT'], 
            'FIELD':['ID',settings_dict['typologyFieldName']],
            'SEPARATE_DISJOINT':False,
            'OUTPUT': temp_folder + '/urbantypelayer_diss.shp'}
        geodata_output['gridded_shp_diss'] = processing.run("native:dissolve", parin)

        ####################################################################################
        ################# Start calculating volumetric fractions ###########################
        ####################################################################################

        # This dictionary retrieve the Code for selected typologies. The Reclassifier uses String values, but later on we need codes in Int

        if settings_dict['spartacus'] == 1:
            # Create wall raster

            # New findwalls from 20241022 
            walls = findwalls(build_arrW, 0.5) # feedback, total) # 0.5 meter difference in kernel filter identify a wall
            saveraster(gdal.Open(filePath_dsm), walls_raster_out, walls)

            # find prefix for filename in IMP-file
            pre = os.path.basename(settings_dict['IMPfile_path'][0])[:os.path.basename(settings_dict['IMPfile_path'][0]).find('_')]

            # new approach using rasterize instead of zonal stat to avoid shapefile overwrite issue in QGIS
            ras_crs = osr.SpatialReference()
            dsm_ref = settings_dict['dsmlayer'].crs().toWkt()
            ras_crs.ImportFromWkt(dsm_ref)
            rasEPSG = ras_crs.GetAttrValue("PROJCS|AUTHORITY", 1)
            geoTransform = dsm.GetGeoTransform()
            minx = geoTransform[0]
            maxy = geoTransform[3]
            maxx = minx + geoTransform[1] * dsm.RasterXSize
            miny = maxy + geoTransform[5] * dsm.RasterYSize

            projwin = str(minx) + ',' + str(maxx) + ',' + str(miny) +',' + str(maxy) + ' [EPSG:' + str(rasEPSG) + ']'
            parin = {
                'INPUT':settings_dict['polyTypolayer'].source(),
                'FIELD':'TypolID',
                'BURN':0,
                'USE_Z':False,
                'UNITS':1, # Georeferenced units
                'WIDTH':pixelSize, 
                'HEIGHT':pixelSize,
                'EXTENT':projwin, 
                'NODATA':0,'OPTIONS':'','DATA_TYPE':4,'INIT':None,'INVERT':False,'EXTRA':'',  # datatyp 5 is wrong?
                'OUTPUT': typo_raster_out
                }
            processing.run("gdal:rasterize", parin)

        ## Calculate total fractions for nonSS runs ##
        # Zonal statstics: mean height of buildings grid/typology
        parin = {
            'INPUT': geodata_output['gridded_shp_diss']['OUTPUT'],
            'INPUT_RASTER':build_raster_out,
            'RASTER_BAND':1,
            'COLUMN_PREFIX':'z_',
            'STATISTICS':[2,4], # 2 mean, 4 = stdev
            'OUTPUT':'TEMPORARY_OUTPUT'}

        # output_name = 'build_count' # or perhaps something like this? + str(int(min_height)) + '_' + str(int(max_height)). now, it overwrites
        geodata_output['mean_build_height'] = processing.run("native:zonalstatisticsfb", parin) 

        # Zonal statstics: Count pixels within each grid/typology
        parin = {
            'INPUT': geodata_output['mean_build_height']['OUTPUT'],
            'INPUT_RASTER':build_raster_out,
            'RASTER_BAND':1,
            'COLUMN_PREFIX':'pixel_',
            'STATISTICS':[0], # Count
            'OUTPUT': 'TEMPORARY_OUTPUT'}

        geodata_output['mean_build_height_pixel_count'] = processing.run("native:zonalstatisticsfb", parin)

        cols = [f.name() for f in geodata_output['mean_build_height_pixel_count']['OUTPUT'].fields()]
        datagen = ([f[col] for col in cols] for f in geodata_output['mean_build_height_pixel_count']['OUTPUT'].getFeatures())

        df_build_frac = pd.DataFrame.from_records(data=datagen, columns=cols)
        df_build_frac = df_build_frac.set_index('ID')  # Set ID as index in df to be able to slice in df 

        df_build_frac['pixel_count'] = df_build_frac['pixel_count'] * pixelSize         
        df_build_frac['volume'] = df_build_frac['pixel_count'] * df_build_frac['z_mean'] 

        df_build_frac = df_build_frac.fillna(0)

        grid_dict = {}       # Dict that holds information on general typologies, uvalues, albedos and emmissivites and fractions
        gridlayoutOut = {}   # Dict that holds information on fractions of, albedos, emmissivitiees and uvalues for GridLaytout.nml
        dir_poly = plugin_dir + '/tempdata/poly_temp.shp' # move later

        if settings_dict['checkBoxTypologies'] == 0:
            QgsProject.instance().removeMapLayer(settings_dict['polyTypolayer'].source())
            del settings_dict['polyTypolayer']

        # loop through each grid (Typologies)
        self.dlg.progressBar.setMaximum(settings_dict['vlayer'].featureCount())
        index = 0
        for f in settings_dict['vlayer'].getFeatures(): 
            id = int(f.attribute(settings_dict['poly_field']))
            print('Processing ID for aggregation: ' + str(id))
            index = index + 1
            self.dlg.progressBar.setValue(index)
            
            # Create new key for each grid_id
            grid_dict[id] = {}
            nonVeg_dict[id] = {}
            gridlayoutOut[id] = {} 
            df_build_frac.loc[id, 'tot_fraction'] = df_build_frac.loc[id, 'volume'] / df_build_frac.loc[id,'volume'].sum()

            # get uvalues etc. from database and fractions from previous fraction calculations
            # TODO Make into function
            for row in df_build_frac.loc[[id]].iterrows():
                typology = int(row[1][settings_dict['typologyFieldName']]) 
                fraction = row[1]['tot_fraction']   
                grid_dict[id][typology] = {}
                grid_dict[id][typology]['SAreaFrac'] = fraction # populate fractions in grid_dict

                # Use locator to avoid this long and complicated pandas slice at all below rows
                # locator selects the seleced 'Spartacus Surface' from the Spartacus surface connected to the building in the selected typology
                locator =  db_dict['Spartacus Surface'].loc[db_dict['NonVeg'].loc[db_dict['Types'].loc[typology]['Buildings']]['Spartacus Surface']]
                grid_dict[id][typology]['uvalue_wall'] = locator['u_value_wall']
                grid_dict[id][typology]['uvalue_roof'] = locator['u_value_roof']
                grid_dict[id][typology]['albedo_roof'] = locator['albedo_roof']
                grid_dict[id][typology]['albedo_wall'] = locator['albedo_wall']
                grid_dict[id][typology]['emissivity_roof'] = locator['emissivity_roof']
                grid_dict[id][typology]['emissivity_wall'] = locator['emissivity_wall']
            
            ## Spartacus ##
            if settings_dict['spartacus'] == 1:
                #vertical info from IMP calc
                ssVect  = pd.read_csv(settings_dict['ss_dir'] + '/' + pre + '_IMPGrid_SS_' + str(id) + '.txt', sep='\s+')

                # Some error check before calculation of gridlayout
                error_output = {}
                vertHeightsIn = settings_dict['vertheights']
                if settings_dict['heightMethod'] == 1: # static levels (taken from interface). Last value > max height
                    if ssVect['z'].max() <= max(vertHeightsIn):
                        error_output = {id : f'zMax ({str(ssVect['z'].max())}) is lower than max fixed height  {str(max(vertHeightsIn))}.'}
                        print('error in ID: ', str(id), f'. zMax is lower than max fixed height {str(max(vertHeightsIn))}.')
                        QMessageBox.critical(None, "Error in Vertical Morphology Spartcus (opt 1)", 'error in ID: ' + str(id) + '. zMax (' + str(ssVect['z'].max()) + 
                                     ') lower than max fixed height ' + str(max(vertHeightsIn)) + '. Use other method or reduce fixed layer height.')
                        self.dlg.progressBar.setValue(index)
                        return

                elif settings_dict['heightMethod'] == 2: # always nlayers layer based on percentiles
                    nlayerOut = settings_dict['nlayers']
                    if ssVect['z'].max() <= nlayerOut:
                        error_output = {id : f'zMax ({str(ssVect['z'].max())}) is to low to use {str(nlayerOut)} vertical layers.'}
                        print('error in ID: ', str(id), f'. zMax is to low to use {str(nlayerOut)} vertical layers.')
                        QMessageBox.critical(None, "Error in Vertical Morphology Spartcus (opt 2)", 'error in ID: ' + str(id) + '. zMax (' + str(ssVect['z'].max()) + 
                                     ') is to low when using ' + str(nlayerOut) + ' vertical layers. Use other method or reduce number of vertical layers.')
                        self.dlg.progressBar.setValue(index)
                        return

                # Determinte height intervals and number of vertical layers in current grid
                heightIntervals, nlayer = getVertheights(
                    ssVect, 
                    settings_dict['heightMethod'], 
                    copy.deepcopy(settings_dict['vertheights']), 
                    settings_dict['nlayers'], 
                    settings_dict['skew'], 
                    id)
                
                # Add errors (if any) to spartacus error dict used later for
                if error_output:        
                    spartacus_error_dict = spartacus_error_dict | error_output

                gridlayoutOut[id]['nlayer'] = nlayer
                gridlayoutOut[id]['height'] = heightIntervals.copy()

                #Access grid geometry
                prov = settings_dict['vlayer'].dataProvider()
                fields = prov.fields()
                attributes = f.attributes()
                geometry = f.geometry()
                feature = QgsFeature()
                feature.setAttributes(attributes)
                feature.setGeometry(geometry)
                writer = QgsVectorFileWriter(dir_poly, "CP1250", fields, prov.wkbType(), prov.crs(), "ESRI shapefile")
                writer.addFeature(feature)
                del writer

                #Clip building, wall and typology raster 
                bigraster = gdal.Open(build_raster_out)
                clip_spec = gdal.WarpOptions(format="GTiff", cutlineDSName=dir_poly, cropToCutline=True)
                gdal.Warp(temp_folder + '/clipbuild.tif', bigraster, options=clip_spec)
                dataset = gdal.Open(temp_folder + '/clipbuild.tif')
                build_array = dataset.ReadAsArray().astype(float)
                bigraster = None
                dataset = None
                
                bigraster = gdal.Open(walls_raster_out)
                clip_spec = gdal.WarpOptions(format="GTiff", cutlineDSName=dir_poly, cropToCutline=True)
                gdal.Warp(temp_folder + '/clipwall.tif', bigraster, options=clip_spec)
                dataset = gdal.Open(temp_folder + '/clipwall.tif')
                wall_array = dataset.ReadAsArray().astype(float)
                bigraster = None
                dataset = None

                bigraster = gdal.Open(typo_raster_out)
                clip_spec = gdal.WarpOptions(format="GTiff", cutlineDSName=dir_poly, cropToCutline=True)
                gdal.Warp(temp_folder + '/cliptypo.tif', bigraster, options=clip_spec)
                dataset = gdal.Open(temp_folder + '/cliptypo.tif')
                typo_array = dataset.ReadAsArray().astype(float)
                bigraster = None
                dataset = None

                # clip dem
                clip_spec = gdal.WarpOptions(format="GTiff", cutlineDSName=dir_poly, cropToCutline=True)
                gdal.Warp(temp_folder + '/clipdem.tif', dem, options=clip_spec)
                dataset = gdal.Open(temp_folder + '/clipdem.tif')
                dem_clip_array = dataset.ReadAsArray().astype(float)
                dataset = None

                # clip dsm
                clip_spec = gdal.WarpOptions(format="GTiff", cutlineDSName=dir_poly, cropToCutline=True)
                gdal.Warp(temp_folder + '/clipdsm.tif', dsm, options=clip_spec)
                dataset = gdal.Open(temp_folder + '/clipdsm.tif')
                dsm_clip_array = dataset.ReadAsArray().astype(float)        
                dataset = None

                buildings_count = count_buildings(dsm_clip_array, dem_clip_array) 
     
                gridlayoutOut[id]['wallAreaGrid'] = wall_array.sum() * pixelSize
                gridlayoutOut[id]['buildings_count'] = buildings_count

                typoList = np.unique(typo_array) 

            # Make a list to count if thera are more than one typology in grid. Test in the if statement below
            typology_list = list(grid_dict[id].keys())

            # Check if aggregation is needed
            # Now we blend typologies and aggregate for new codes
            if len(typology_list) > 1:
                nonVeg_dict[id]['Paved']     = blend_SUEWS_NonVeg(grid_dict[id], db_dict, parameter_dict, zenodo, 'Paved') 
                nonVeg_dict[id]['Buildings'] = blend_SUEWS_NonVeg(grid_dict[id], db_dict, parameter_dict, zenodo, 'Buildings') 

            # if only one typology exists, no need to aggregate/combine/blend
            else:
                if settings_dict['checkBoxTypologies'] == 0:

                    nonVeg_dict[id]['Paved'] = fill_SUEWS_NonVeg_typologies(db_dict, parameter_dict, settings_dict['Paved'], zenodo, 'Paved')
                    nonVeg_dict[id]['Buildings'] = fill_SUEWS_NonVeg_typologies( db_dict, parameter_dict, settings_dict['Buildings'], zenodo, 'Buildings')
                else:
                    nonVeg_dict[id]['Paved'] = fill_SUEWS_NonVeg_typologies(db_dict, parameter_dict, settings_dict['Paved'], zenodo, 'Paved')
                    nonVeg_dict[id]['Buildings'] = fill_SUEWS_NonVeg_typologies( db_dict, parameter_dict, settings_dict['Buildings'], zenodo, 'Buildings')
                
            nonVeg_dict[id]['Bare Soil'] = fill_SUEWS_NonVeg_typologies(db_dict, parameter_dict, settings_dict['Bare Soil'], zenodo, 'Bare Soil')
            gridlayoutOut[id]['vertical_layers'] = {}
            gridlayoutOut[id]['vertical_layers'] = ss_calc_gridlayout(build_array, wall_array, typoList, typo_array,  gridlayoutOut, id, db_dict, zenodo, settings_dict['ss_dir'], pre, grid_dict[id]),
        
        # write to SUEWS_NonVeg
           
        # Write SUEWS.txt files SUEWS_veg, SUEWS_AnthropogenicEmission, SUEWS_Water and SUEWS_Conductance
        veg_dict = fill_SUEWS_Veg(db_dict, settings_dict, parameter_dict,  zenodo)
    
        # Save Profiles
        profiles_dict = profiles_to_dict(settings_dict, db_dict['Profiles'], db_dict['References'])

        # set correct values and write txt.files based on the parameters found at country/regional level 
        snow_dict = fill_SUEWS_Snow(parameter_dict['SnowCode'], db_dict, zenodo)
        water_dict = fill_SUEWS_Water(parameter_dict['Water'], db_dict, parameter_dict, zenodo)

        cond_dict = db_dict['Conductance'].loc[parameter_dict['Conductance']].to_dict()
        cond_dict['Code'] = parameter_dict['Conductance']

                
        leaf_cycle = self.leaf_cycle


        # ################################################################################################################################
        #                                               Writing SiteSelect.txt  (now, yaml)     
        # ################################################################################################################################

        ind = 1
        year = None     # Not sure what this is, but it works
        year2 = None    # Not surre what this is, but it works

        if settings_dict['Metfile_path'] is None:
            QMessageBox.critical(None, "Error", "Meteorological data file has not been provided,"
                                        " please check the main tab")
            return
        
        elif os.path.isfile(settings_dict['Metfile_path'][0]):
            with open(settings_dict['Metfile_path'][0]) as file:
                next(file)
                for line in file:
                    split = line.split()
                    if year == split[0]:
                        break
                    else:
                        if year2 == split[0]:
                            year = split[0]
                            break
                        elif year is None:
                            year = split[0]
                        else:
                            year2 = split[0]

            # figure out the time res of input file
            if ind == 1:
                # met_old = np.genfromtxt(settings_dict['Metfile_path'][0], skip_header=1, skip_footer=2)
                # met_id = met_old[:, 1]
                # it = met_old[:, 2]
                # imin = met_old[:, 3]
                # dectime0 = met_id[0] + it[0] / 24 + imin[0] / (60 * 24)
                # dectime1 = met_id[1] + it[1] / 24 + imin[1] / (60 * 24)
                # res = int(np.round((dectime1 - dectime0) * (60 * 24)))
                # ind = 999

                # YYYY = int32(np.min(met_old[:, 0]))

                # start_date = ''
                # end_date = ''
                # # --- save met-file --- #
                # data_out = self.output_dir[0] + "/" + self.file_code + '_' + str(YYYY) + '_data_' + str(res) + '.txt'
                # header = '%iy id it imin Q* QH QE Qs Qf Wind RH Td press rain Kdn snow ldown fcld wuh xsmd lai_hr ' \
                #          'Kdiff Kdir Wd'
                # numformat = '%3d %2d %3d %2d %6.2f %6.2f %6.2f %6.2f %6.2f %6.2f %6.2f %6.2f %6.2f %6.4f %6.2f %6.2f ' \
                #             '%6.2f %6.2f %6.4f %6.2f %6.2f %6.2f %6.2f %6.2f'

                # np.savetxt(data_out, met_old, fmt=numformat, delimiter=' ', header=header, comments='')

                # Define the column names (you can adjust this to match the actual file)
                column_names = [
                    'iy', 'id', 'it', 'imin', 'qn', 'qh', 'qe', 'qs', 'qf', 'U', 'RH', 'Td', 'press', 'rain',
                    'kdown', 'snow', 'ldown', 'fcld', 'wuh', 'xsmd', 'lai', 'kdiff', 'kdir', 'wdir'
                ]

                df = pd.read_csv(settings_dict['Metfile_path'][0], delim_whitespace=True, skiprows=1, names=column_names)

                # 2. Construct datetime index from columns: iy (year), id (DOY), it (hour), imin (minute)
                df['datetime'] = pd.to_datetime(df['iy'], format='%Y') + pd.to_timedelta(df['id'] - 1, unit='D') + \
                                pd.to_timedelta(df['it'], unit='h') + pd.to_timedelta(df['imin'], unit='m')
                df.set_index('datetime', inplace=True)

                # 3. Compute time resolution in minutes
                dectime0 = df['iy'].iloc[0] + df['it'].iloc[0] / 24 + df['imin'].iloc[0] / (60 * 24)
                dectime1 = df['iy'].iloc[1] + df['it'].iloc[1] / 24 + df['imin'].iloc[1] / (60 * 24)
                res = int(round((dectime1 - dectime0) * 60 * 24))

                # Get start and end date
                start_date = df.index[0].strftime('%Y-%m-%d')
                end_date = df.index[-1].strftime('%Y-%m-%d')

                # 4. Define output path
                YYYY = int(df['iy'].min())
                data_out = f'{self.output_dir[0]}/{self.file_code}_{YYYY}_data_{res}.txt'

                # 5. Save the file using .to_csv (formatted like np.savetxt)
                df_out = df[column_names]  # Preserve original order
                header = 'iy id it imin Q* QH QE Qs Qf Wind RH Td press rain Kdn snow ldown fcld wuh xsmd lai_hr ' \
                        'Kdiff Kdir Wd'

                # Save with formatting
                np.savetxt(data_out, df_out.to_numpy(), fmt='%3d %2d %3d %2d %6.2f %6.2f %6.2f %6.2f %6.2f %6.2f '
                            '%6.2f %6.2f %6.2f %6.4f %6.2f %6.2f %6.2f %6.2f %6.4f %6.2f %6.2f %6.2f %6.2f %6.2f',
                            delimiter=' ', header=header, comments='')
        else:
            QMessageBox.critical(None, "Error",
                                    "Could not find the file containing meteorological data")
            return

        # ss_dict, siteselect_dict. Populate dict that will go to yaml
        # this section is for all grids. 
        ss_dict = {
            'name': 'sample_config',
            'description': 'this is a sample config for testing purposes ONLY - values are not realistic',

            'model': {
                'control': {
                    'tstep': 300,
                    'forcing_file': {'value': data_out},
                    'output_file':  'output.txt',
                    'diagnose': 0,
                    'start_time': start_date,
                    'end_time': end_date
                },
                'physics': {
                    'netradiationmethod': {'value': 3}, #changed from 1 FL
                    'emissionsmethod': {'value' : db_dict['AnthropogenicEmission'].loc[parameter_dict['AnthropogenicCode'],'Model']},
                    'storageheatmethod': {'value': 1}, #Changed from 3 FL
                    'ohmincqf': {'value': 0},
                    'roughlenmommethod': {'value': 1}, # Values based on Kent et al. 2017
                    'roughlenheatmethod': {'value': 2},
                    'stabilitymethod': {'value': 3},
                    'smdmethod': {'value': 0},
                    'waterusemethod': {'value': 0},
                    'diagmethod': {'value': 0},
                    'faimethod': {'value': 0},
                    'localclimatemethod': {'value': 0},
                    'snowuse': {'value': 0},
                    'stebbsmethod': {'value': 0},
                    'gsmodel': {'value': cond_dict['gsModel']},
                },
            },
            'sites' : []
        }
        
        # Loop Start for each Grid
        for feature in settings_dict['vlayer'].getFeatures():

            feat_id = int(feature.attribute(settings_dict['poly_field']))
    
            print('Processing ID: ' + str(feat_id) + ' for grid specific parameters')

            old_cs = osr.SpatialReference()
            vlayer_ref = settings_dict['vlayer'].crs().toWkt()
            old_cs.ImportFromWkt(vlayer_ref)

            wgs84_wkt = """
            GEOGCS["WGS 84",
                DATUM["WGS_1984",
                    SPHEROID["WGS 84",6378137,298.257223563,
                        AUTHORITY["EPSG","7030"]],
                    AUTHORITY["EPSG","6326"]],
                PRIMEM["Greenwich",0,
                    AUTHORITY["EPSG","8901"]],
                UNIT["degree",0.01745329251994328,
                    AUTHORITY["EPSG","9122"]],
                AUTHORITY["EPSG","4326"]]"""

            new_cs = osr.SpatialReference()
            new_cs.ImportFromWkt(wgs84_wkt)

            transform = osr.CoordinateTransformation(old_cs, new_cs)

            centroid = feature.geometry().centroid().asPoint()
            area = feature.geometry().area()

            if settings_dict['map_units'] == 0:
                hectare = area # meter

            elif settings_dict['map_units'] == 1:
                hectare = area / 107640. # square foot

            else:
                hectare = area
            # gdalver == GDAL-version
            gdalver = float(gdal.__version__[0])
            lonlat = transform.TransformPoint(centroid.x(), centroid.y())
            
            altitude = 1    # TODO Is this not set?
            day = 1         # 
            hour = 0        #
            minute = 0      # 

            if settings_dict['LCF_from_file']:
                LCF_paved     = LCF_dict[feat_id]['Paved']
                LCF_buildings = LCF_dict[feat_id]['Buildings']
                LCF_evergreen = LCF_dict[feat_id]['EvergreenTrees']
                LCF_decidious = LCF_dict[feat_id]['DecidiousTrees']
                LCF_grass     = LCF_dict[feat_id]['Grass']
                LCF_baresoil  = LCF_dict[feat_id]['Baresoil']
                LCF_water     = LCF_dict[feat_id]['Water']
            

            # 
            irrFr_EveTr = 0
            irrFr_DecTr = 0
            irrFr_Grass = 0
            IrrFr_Bldgs = 0
            IrrFr_Paved = 0
            IrrFr_Water = 0
            IrrFr_BSoil = 0

            # TrafficRate_WD = 0.0135 ## Already in dict
            # TrafficRate_WE = 0.0095 ## Already in dict

            # QF0_BEU_WD = 0.88 ## Already in dict
            # QF0_BEU_WE = 0.88 ## Already in dict
           
            if settings_dict['IMP_from_file']:
                IMP_heights_mean = IMP_dict[feat_id]['zH']
                IMP_z0 = IMP_dict[feat_id]['z0']
                IMP_zd = IMP_dict[feat_id]['zd']
                IMP_fai = IMP_dict[feat_id]['fai']
                IMP_max = IMP_dict[feat_id]['zHmax']
                IMP_sd = IMP_dict[feat_id]['zHstd']
                IMP_wai = IMP_dict[feat_id]['wai']

            if settings_dict['IMPveg_from_file']:
                IMPveg_heights_mean_eve = IMPveg_dict[feat_id]['zH']
                IMPveg_heights_mean_dec = IMPveg_dict[feat_id]['zH']
                IMPveg_fai_eve = IMPveg_dict[feat_id]['fai']
                IMPveg_fai_dec = IMPveg_dict[feat_id]['fai']
                IMPveg_max_eve = IMPveg_dict[feat_id]['zHmax']  #TODO not used yet
                IMPveg_sd_eve = IMPveg_dict[feat_id]['zHmax']  #TODO not used yet
                IMPveg_max_dec = IMPveg_dict[feat_id]['zHstd']
                IMPveg_sd_dec = IMPveg_dict[feat_id]['zHstd']

            # New calcualtion of rouhgness params v2017 (Kent et al. 2017b)
            # Evergreen not yet included in the calculations
            LCF_de = float(LCF_decidious)
            LCF_ev = float(LCF_evergreen)
            LCF_bu = float(LCF_buildings)
            LCF_tr = LCF_de + LCF_ev # temporary fix while ev and de is not separated, issue 155
            if (LCF_de  == 0 and LCF_ev == 0 and LCF_bu == 0):
                zH = 0
                zMAx = 0
            else:
                zH = (float(IMP_heights_mean) * LCF_bu + float(IMPveg_heights_mean_eve) * LCF_ev + float(IMPveg_heights_mean_dec) * LCF_de) / (LCF_bu + LCF_ev + LCF_de)                    
                zMax = max(float(IMPveg_max_dec),float(IMP_max))

            if (LCF_de  == 0 and LCF_ev == 0 and LCF_bu == 0):
                sdComb = 0
                IMP_z0 = 0
                IMP_zd = 0
                # sdTree = np.sqrt((IMPveg_sd_eve ^ 2 / LCF_evergreen * area) + (IMPveg_sd_dec ^ 2 / LCF_decidious * area))  # not used yet
            elif (LCF_tr == 0 and LCF_bu != 0):
                sdComb = np.sqrt(float(IMP_sd) ** 2. / (LCF_bu * float(area)))  # Fix (fLCF_bu) issue #162
            elif (LCF_tr != 0 and LCF_bu == 0):
                sdComb = np.sqrt(float(IMPveg_sd_dec) ** 2. / (LCF_tr * float(area)))
            elif (LCF_tr != 0 and LCF_bu != 0):
                sdComb = np.sqrt(float(IMPveg_sd_dec) ** 2. / (LCF_tr * float(area)) + float(IMP_sd) ** 2. / (LCF_bu * float(area)))

            pai = LCF_bu + LCF_ev + LCF_de
            
            # paiall = (planareaB + planareaV) / AT
            porosity = 0.2  # This should change with season. Net, set for Summer
            Pv = ((-1.251 * porosity ** 2) / 1.2) + ((0.489 * porosity) / 1.2) + (0.803 / 1.2)  # factor accounting for porosity to correct total fai in roughness calc Kent et al. 2017b
            # faiall_rgh = (frontalareaB + (Pv * frontalareaV)) / (AT / (1 / scale))  # frontal area used in roughness calculation Kent et al. 2017b
            fai = Pv * (float(IMPveg_fai_eve) + float(IMPveg_fai_dec)) + float(IMP_fai)
            if (fai == 0. and pai == 1.):
                IMP_z0 = 0.
                IMP_zd = zH
            elif (fai == 0. and pai < 1.):
                IMP_z0 = 0.
                IMP_zd = 0.
            else:
                IMP_zd, IMP_z0 = rg.RoughnessCalc("Kan", zH, fai, pai, zMax, sdComb)

            # clean up and give open country values if non-existant
            if np.isnan(IMP_z0) or IMP_z0 < 0.03:
                IMP_z0 = 0.03
            if np.isnan(IMP_zd) or IMP_zd < 0.2:
                IMP_zd = 0.2

            # # new for z (2017)
            try:
                z = ((float(IMP_heights_mean) * float(LCF_buildings) + float(IMPveg_heights_mean_eve) * float(LCF_evergreen) +
                    float(IMPveg_heights_mean_dec) * float(LCF_decidious)) / (float(LCF_buildings) + float(LCF_evergreen) + float(LCF_decidious))) * 3
            except:
                z = 10.
            if z < 10.:
                z = 10.

            if settings_dict['pop_density'] is not None:
                pop_density_night = feature.attribute(settings_dict['pop_density'])
            else:
                pop_density_night = -999

            if settings_dict['daypop'] == 1:
                pop_density_day = feature.attribute(settings_dict['pop_density_day'])
            else:
                pop_density_day = pop_density_night

            # TODO Not sure on these settings
            LUMPS_drate = 0.25
            LUMPS_Cover = 1
            LUMPS_MaxRes = 10
            NARP_Trans = 1

            # flow_change = 0
            RunoffToWater = 0.1
            PipeCap = 100
            
            # name-description + site/landcover
            TrafficRate_WD = 0.0135 ## Already in dict
            TrafficRate_WE = 0.0095 ## Already in dict
            AnEm = fill_AnEm_yaml(db_dict, parameter_dict['AnthropogenicCode'], profiles_dict, parameter_dict, settings_dict['start_DLS'], settings_dict['end_DLS'], TrafficRate_WD, TrafficRate_WE, pop_density_night, pop_density_day, zenodo)

            # Lägg till grids i listan inom en loop
            properties = {
                'lat': {'value': round(float(lonlat[0]),3)},
                'lng': {'value': round(float(lonlat[1]),3)}, 
                'alt': {'value': altitude},
                'timezone': {'value': settings_dict['utc']},
                'surfacearea': {'value': round(hectare ,2)},
                'z': {'value': float('%.3f' % z)},
                'z0m_in': {'value': float('%.3f' % IMP_z0)},
                'zdm_in': {'value': float('%.3f' % IMP_zd)},
                'pipecapacity': {'value': PipeCap},
                'runofftowater': {'value': RunoffToWater},
                'narp_trans_site': {'value': NARP_Trans},
                
                'lumps': {
                    'raincover': {'value': LUMPS_Cover},
                    'rainmaxres': {'value': LUMPS_MaxRes},
                    'drainrt': {'value': LUMPS_drate},
                    'veg_type': {'value': 1}  # TODO WHAT?
                    },

                'spartacus': { # At the moment, these variables are just standard. we dont know from where they come
                        'air_ext_lw': {'value': 0.0},
                        'air_ext_sw': {'value': 0.0},
                        'air_ssa_lw': {'value': 0.5},
                        'air_ssa_sw': {'value': 0.5},
                        'ground_albedo_dir_mult_fact': {'value': 1.0},
                        'n_stream_lw_urban': {'value': 2},
                        'n_stream_sw_urban': {'value': 2},
                        'n_vegetation_region_urban': {'value': 1},
                        'sw_dn_direct_frac': {'value': 0.5},
                        'use_sw_direct_albedo': {'value': 1.0},
                        'veg_contact_fraction_const': {'value': 0.5},
                        'veg_fsd_const': {'value': 0.5},
                        'veg_ssa_lw': {'value': 0.5},
                        'veg_ssa_sw': {'value': 0.5}
                    },

                # TODO AS OF NOW, THIS IS JUST LEFT AS IT IS SINCE WE DONT KNOW ANYTHING ABOUT THESE PARAMETERS
                'stebbs': {
                    'WallInternalConvectionCoefficient': {'value': 0.0},
                    'InternalMassConvectionCoefficient': {'value': 0.0},
                    'FloorInternalConvectionCoefficient': {'value': 0.0},
                    'WindowInternalConvectionCoefficient': {'value': 0.0},
                    'WallExternalConvectionCoefficient': {'value': 0.0},
                    'WindowExternalConvectionCoefficient': {'value': 0.0},
                    'GroundDepth': {'value': 0.0},
                    'ExternalGroundConductivity': {'value': 0.0},
                    'IndoorAirDensity': {'value': 0.0},
                    'IndoorAirCp': {'value': 0.0},
                    'WallBuildingViewFactor': {'value': 0.0},
                    'WallGroundViewFactor': {'value': 0.0},
                    'WallSkyViewFactor': {'value': 0.0},
                    'MetabolicRate': {'value': 0.0},
                    'LatentSensibleRatio': {'value': 0.0},
                    'ApplianceRating': {'value': 0.0},
                    'TotalNumberofAppliances': {'value': 0},
                    'ApplianceUsageFactor': {'value': 0.0},
                    'HeatingSystemEfficiency': {'value': 0.0},
                    'MaxCoolingPower': {'value': 0.0},
                    'CoolingSystemCOP': {'value': 0.0},
                    'VentilationRate': {'value': 0.0},
                    'IndoorAirStartTemperature': {'value': 0.0},
                    'IndoorMassStartTemperature': {'value': 0.0},
                    'WallIndoorSurfaceTemperature': {'value': 0.0},
                    'WallOutdoorSurfaceTemperature': {'value': 0.0},
                    'WindowIndoorSurfaceTemperature': {'value': 0.0},
                    'WindowOutdoorSurfaceTemperature': {'value': 0.0},
                    'GroundFloorIndoorSurfaceTemperature': {'value': 0.0},
                    'GroundFloorOutdoorSurfaceTemperature': {'value': 0.0},
                    'WaterTankTemperature': {'value': 0.0},
                    'InternalWallWaterTankTemperature': {'value': 0.0},
                    'ExternalWallWaterTankTemperature': {'value': 0.0},
                    'WaterTankWallThickness': {'value': 0.0},
                    'MainsWaterTemperature': {'value': 0.0},
                    'WaterTankSurfaceArea': {'value': 0.0},
                    'HotWaterHeatingSetpointTemperature': {'value': 0.0},
                    'HotWaterTankWallEmissivity': {'value': 0.0},
                    'DomesticHotWaterTemperatureInUseInBuilding': {'value': 0.0},
                    'InternalWallDHWVesselTemperature': {'value': 0.0},
                    'ExternalWallDHWVesselTemperature': {'value': 0.0},
                    'DHWVesselWallThickness': {'value': 0.0},
                    'DHWWaterVolume': {'value': 0.0},
                    'DHWSurfaceArea': {'value': 0.0},
                    'DHWVesselEmissivity': {'value': 0.0},
                    'HotWaterFlowRate': {'value': 0.0},
                    'DHWDrainFlowRate': {'value': 0.0},
                    'DHWSpecificHeatCapacity': {'value': 0.0},
                    'HotWaterTankSpecificHeatCapacity': {'value': 0.0},
                    'DHWVesselSpecificHeatCapacity': {'value': 0.0},
                    'DHWDensity': {'value': 0.0},
                    'HotWaterTankWallDensity': {'value': 0.0},
                    'DHWVesselDensity': {'value': 0.0},
                    'HotWaterTankBuildingWallViewFactor': {'value': 0.0},
                    'HotWaterTankInternalMassViewFactor': {'value': 0.0},
                    'HotWaterTankWallConductivity': {'value': 0.0},
                    'HotWaterTankInternalWallConvectionCoefficient': {'value': 0.0},
                    'HotWaterTankExternalWallConvectionCoefficient': {'value': 0.0},
                    'DHWVesselWallConductivity': {'value': 0.0},
                    'DHWVesselInternalWallConvectionCoefficient': {'value': 0.0},
                    'DHWVesselExternalWallConvectionCoefficient': {'value': 0.0},
                    'DHWVesselWallEmissivity': {'value': 0.0},
                    'HotWaterHeatingEfficiency': {'value': 0.0},
                    'MinimumVolumeOfDHWinUse': {'value': 0.0}
                },

                'building_archetype': {
                    'BuildingType': 'SampleType',
                    'BuildingName': 'SampleBuilding',
                    'BuildingCount': {'value': 1},
                    'Occupants': {'value': 1},
                    'stebbs_Height': {'value': 10.0},
                    'FootprintArea': {'value': 64.0},
                    'WallExternalArea': {'value': 80.0},
                    'RatioInternalVolume': {'value': 0.0},
                    'WWR': {'value': 0.2},
                    'WallThickness': {'value': 20.0},
                    'WallEffectiveConductivity': {'value': 60.0},
                    'WallDensity': {'value': 1600.0},
                    'WallCp': {'value': 850.0},
                    'Wallx1': {'value': 1.0},
                    'WallExternalEmissivity': {'value': 0.9},
                    'WallInternalEmissivity': {'value': 0.9},
                    'WallTransmissivity': {'value': 0.0},
                    'WallAbsorbtivity': {'value': 0.8},
                    'WallReflectivity': {'value': 0.2},
                    'FloorThickness': {'value': 0.2},
                    'GroundFloorEffectiveConductivity': {'value': 0.15},
                    'GroundFloorDensity': {'value': 500.0},
                    'GroundFloorCp': {'value': 1500.0},
                    'WindowThickness': {'value': 0.015},
                    'WindowEffectiveConductivity': {'value': 1.0},
                    'WindowDensity': {'value': 2500.0},
                    'WindowCp': {'value': 840.0},
                    'WindowExternalEmissivity': {'value': 0.9},
                    'WindowInternalEmissivity': {'value': 0.9},
                    'WindowTransmissivity': {'value': 0.9},
                    'WindowAbsorbtivity': {'value': 0.01},
                    'WindowReflectivity': {'value': 0.09},
                    'InternalMassDensity': {'value': 0.0},
                    'InternalMassCp': {'value': 0.0},
                    'InternalMassEmissivity': {'value': 0.0},
                    'MaxHeatingPower': {'value': 0.0},
                    'WaterTankWaterVolume': {'value': 0.0},
                    'MaximumHotWaterHeatingPower': {'value': 0.0},
                    'HeatingSetpointTemperature': {'value': 15.0},
                    'CoolingSetpointTemperature': {'value': 25.0}
                    },

                # Conductance
                'conductance': {
                    'g_max': {'value': cond_dict['G1']},
                    'g_k': {'value': cond_dict['G2']},
                    'g_q_base': {'value': cond_dict['G3']},
                    'g_q_shape': {'value': cond_dict['G4']},
                    'g_t': {'value': cond_dict['G5']},
                    'g_sm': {'value': cond_dict['G6']},
                    'kmax': {'value': cond_dict['Kmax']},
                    # 'gsmodel': {'value': cond_dict['gsModel']}, # Moved to physics 20250626
                    's1': {'value': cond_dict['S1']},
                    's2': {'value': cond_dict['S2']},
                    'tl': {'value': cond_dict['TL']},
                    'th': {'value': cond_dict['TH']},
                    'ref': {
                        'desc': db_dict['Conductance'].loc[cond_dict['Code'], 'nameOrigin'],
                        'ID': str(cond_dict['Code']),
                        'DOI':  zenodo,
                         }
                    },

                'irrigation': fill_irrigation_yaml(db_dict['Irrigation'].loc[parameter_dict['IrrigationCode']] , profiles_dict, zenodo),
                
                'anthropogenic_emissions' : AnEm,
                
                'snow' : snow_dict, #,fill_snow_yaml(db_dict['Snow'], snow_dict, profiles_dict, nonVeg_dict[feat_id], zenodo),

                'land_cover': {
                    'paved': fill_nonveg_yaml(nonVeg_dict[feat_id], db_dict, 'Paved', LCF_paved, IrrFr_Paved, 0, 0, zenodo), # Paved has no mean height or FAI
                    'bldgs': fill_nonveg_yaml(nonVeg_dict[feat_id], db_dict, 'Buildings', LCF_buildings, IrrFr_Bldgs, IMP_fai, IMP_heights_mean, zenodo),
                    'evetr': fill_veg_yaml(veg_dict, db_dict, 'Evergreen Tree', LCF_evergreen, irrFr_EveTr, IMPveg_fai_eve, IMPveg_heights_mean_eve, parameter_dict['IrrigationCode'], zenodo),
                    'dectr': fill_veg_yaml(veg_dict, db_dict, 'Deciduous Tree', LCF_decidious, irrFr_DecTr, IMPveg_fai_dec, IMPveg_heights_mean_dec,parameter_dict['IrrigationCode'], zenodo),
                    'grass': fill_veg_yaml(veg_dict, db_dict, 'Grass', LCF_grass, irrFr_Grass, 0, 0, parameter_dict['IrrigationCode'], zenodo), # grass has no mean height or FAI
                    'bsoil': fill_bare_soil_yaml(nonVeg_dict[feat_id]['Bare Soil'], db_dict, LCF_baresoil, IrrFr_BSoil, zenodo) ,
                    'water': fill_water_yaml(water_dict, db_dict, LCF_water, IrrFr_Water, zenodo),
                },  
                'vertical_layers' : gridlayoutOut[feat_id]['vertical_layers'][0],
                'n_buildings':{
                    'value': gridlayoutOut[feat_id]['buildings_count']}, # buildings_count_dict[feat_id]
                'h_std':
                    {'value': IMP_sd},
                'lambda_c' : 
                    {'value' : round(float((gridlayoutOut[feat_id]['wallAreaGrid']) / (hectare * LCF_buildings)) + 1, 4)}
            }

            initial_states = {
                'snowalb': {'value': 0.3},

                'paved': {
                'state': {'value': 0.0},
                'soilstore': {'value': 10},
                'snowfrac': {'value': 0.0},
                'snowpack': {'value': 0.0},
                'icefrac': {'value': 0.0},
                'snowwater': {'value': 0.0},
                'snowdens': {'value': 0.0},
                'temperature': {'value': [15.0, 15.0, 15.0, 15.0, 15.0]},
                'tsfc': {'value': 15.0},
                'tin': {'value': 20.0}
                },

                'bldgs': {
                'state': {'value': 0.0},
                'soilstore': {'value': 10},
                'snowfrac': {'value': 0.0},
                'snowpack': {'value': 0.0},
                'icefrac': {'value': 0.0},
                'snowwater': {'value': 0.0},
                'snowdens': {'value': 0.0},
                'temperature': {'value': [15.0, 15.0, 15.0, 15.0, 15.0]},
                'tsfc': {'value': 15.0},
                'tin': {'value': 20.0}
                },

                'evetr': {
                'state': {'value': 0.0},
                'soilstore': {'value': 10},
                'snowfrac': {'value': 0.0},
                'snowpack': {'value': 0.0},
                'icefrac': {'value': 0.0},
                'snowwater': {'value': 0.0},
                'snowdens': {'value': 0.0},
                'temperature': {'value': [15.0, 15.0, 15.0, 15.0, 15.0]},
                'tsfc': {'value': 15.0},
                'tin': {'value': 20.0},
                'alb_id': {'value': leaf_cycle_dict[leaf_cycle]['albEveTr0']},
                'lai_id': {'value': leaf_cycle_dict[leaf_cycle]['laiinitialevetr']},
                'gdd_id': {'value': leaf_cycle_dict[leaf_cycle]['gdd_1_0']},
                'sdd_id': {'value': leaf_cycle_dict[leaf_cycle]['gdd_2_0']},
                'wu': {
                    'wu_total': {'value': 0.0},
                    'wu_auto': {'value': 0.0},
                    'wu_manual': {'value': 0.0}
                }
                },

                'dectr': {
                'state': {'value': 0.0},
                'soilstore': {'value': 10},
                'snowfrac': {'value': 0.0},
                'snowpack': {'value': 0.0},
                'icefrac': {'value': 0.0},
                'snowwater': {'value': 0.0},
                'snowdens': {'value': 0.0},
                'temperature': {'value': [15.0, 15.0, 15.0, 15.0, 15.0]},
                'tsfc': {'value': 15.0},
                'tin': {'value': 20.0},
                'alb_id': {'value': leaf_cycle_dict[leaf_cycle]['albDecTr0']},
                'lai_id': {'value': leaf_cycle_dict[leaf_cycle]['laiinitialdectr']},
                'gdd_id': {'value': leaf_cycle_dict[leaf_cycle]['gdd_1_0']},
                'sdd_id': {'value': leaf_cycle_dict[leaf_cycle]['gdd_2_0']},
                'wu': {
                    'wu_total': {'value': 0.0},
                    'wu_auto': {'value': 0.0},
                    'wu_manual': {'value': 0.0}
                },
                'porosity_id': {'value': leaf_cycle_dict[leaf_cycle]['porosity0']},
                'decidcap_id': {'value': leaf_cycle_dict[leaf_cycle]['decidCap0']}
                },

                'grass': {
                'state': {'value': 0.0},
                'soilstore': {'value': 10},
                'snowfrac': {'value': 0.0},
                'snowpack': {'value': 0.0},
                'icefrac': {'value': 0.0},
                'snowwater': {'value': 0.0},
                'snowdens': {'value': 0.0},
                'temperature': {'value': [15.0, 15.0, 15.0, 15.0, 15.0]},
                'tsfc': {'value': 15.0},
                'tin': {'value': 20.0},
                'alb_id': {'value': leaf_cycle_dict[leaf_cycle]['albGrass0']},
                'lai_id': {'value': leaf_cycle_dict[leaf_cycle]['laiinitialgrass']},
                'gdd_id': {'value': leaf_cycle_dict[leaf_cycle]['gdd_1_0']},
                'sdd_id': {'value': leaf_cycle_dict[leaf_cycle]['gdd_2_0']},
                'wu': {
                    'wu_total': {'value': 0.0},
                    'wu_auto': {'value': 0.0},
                    'wu_manual': {'value': 0.0}
                },
                },

                'bsoil': {
                'state': {'value': 0.0},
                'soilstore': {'value': 10},
                'snowfrac': {'value': 0.0},
                'snowpack': {'value': 0.0},
                'icefrac': {'value': 0.0},
                'snowwater': {'value': 0.0},
                'snowdens': {'value': 0.0},
                'temperature': {'value': [15.0, 15.0, 15.0, 15.0, 15.0]},
                'tsfc': {'value': 15.0},
                'tin': {'value': 20.0}
                },

                'water': {
                'state': {'value': 20000.0},
                'soilstore': {'value': 10},
                'snowfrac': {'value': 0.0},
                'snowpack': {'value': 0.0},
                'icefrac': {'value': 0.0},
                'snowwater': {'value': 0.0},
                'snowdens': {'value': 0.0},
                'temperature': {'value': [15.0, 15.0, 15.0, 15.0, 15.0]},
                'tsfc': {'value': 15.0},
                'tin': {'value': 20.0}
                },

                'roofs': [{
                    'state': {'value': 0.0},
                    'soilstore': {'value': 10},
                    'snowfrac': {'value': 0.0},
                    'snowpack': {'value': 0.0},
                    'icefrac': {'value': 0.0},
                    'snowwater': {'value': 0.0},
                    'snowdens': {'value': 0.0},
                    'temperature': {'value': [15.0, 15.0, 15.0, 15.0, 15.0]},
                    'tsfc': {'value': 15.0},
                    'tin': {'value': 20.0}
                    }] * gridlayoutOut[feat_id]['nlayer'],
                'walls': [{
                    'state': {'value': 0.0},
                    'soilstore': {'value': 10},
                    'snowfrac': {'value': 0.0},
                    'snowpack': {'value': 0.0},
                    'icefrac': {'value': 0.0},
                    'snowwater': {'value': 0.0},
                    'snowdens': {'value': 0.0},
                    'temperature': {'value': [15.0, 15.0, 15.0, 15.0, 15.0]},
                    'tsfc': {'value': 15.0},
                    'tin': {'value': 20.0}
                    }] * gridlayoutOut[feat_id]['nlayer']
            }
        
            grid = {
                'name':  f'grid no: {str(feat_id)}',
                'gridiv':  feat_id,
                'properties': copy.deepcopy(properties),
                'initial_states' : copy.deepcopy(initial_states)
            }
            
            grid = check_fraction_consistency(grid)
            
            ss_dict['sites'].append(grid)
            
        # Convert values in the nested dictionary
        ss_dict_native = convert_numpy_types(ss_dict)

        # Spara dictionary till en .yml-fil
        
        with open(save_txt_folder + settings_dict['file_code'] + '.yml', 'w') as file:
            yaml.dump(ss_dict_native, file, sort_keys = False)

        # SUEWSConfig(**ss_dict_native)

        # # If Spartacus dict is not empty, give user a warning. 
        if  spartacus_error_dict:
            error_string = ''
            for keys in list(spartacus_error_dict.keys()):
                error_string = error_string  + f'\n\n Error in Grid: {str(keys)} : {spartacus_error_dict[keys]}'
            
            error_string = error_string + '\n\nCheck Python console to find this information again'

            iface.messageBar().pushMessage("Process completed with warnings from Spartacus", error_string, level=Qgis.Warning)
            
            # QMessageBox.critical(None, "Run complete but with Spartacus Vertical morphology errors", error_string)
        else:
            # iface.messageBar().pushMessage("Process completed", "Input files for SUEWS generated", level=Qgis.Success)
            QMessageBox.information(None, 'Process Complete', "Input files for SUEWS generated")

        self.dlg.progressBar.setValue(0)

    # def write_to_init(self, initfilein, initfileout):
    #     LeafCycle = self.leaf_cycle
    #     SoilMoisture = self.soil_moisture
    #     moist = int(SoilMoisture * 1.5)
    #     snowinitially = 0

    #     nml = f90nml.read(initfilein)

    #     nml['initialconditions']['soilstorepavedstate'] = moist
    #     nml['initialconditions']['soilstorebldgsstate'] = moist
    #     nml['initialconditions']['soilstoreevetrstate'] = moist
    #     nml['initialconditions']['soilstoredectrstate'] = moist
    #     nml['initialconditions']['soilstoregrassstate'] = moist
    #     nml['initialconditions']['soilstorebsoilstate'] = moist

    #     # Based on London data
    #     if LeafCycle == 1:  # Winter
    #         nml['initialconditions']['gdd_1_0'] = 0
    #         nml['initialconditions']['gdd_2_0'] = -450
    #         nml['initialconditions']['laiinitialevetr'] = 4
    #         nml['initialconditions']['laiinitialdectr'] = 1
    #         nml['initialconditions']['laiinitialgrass'] = 1.6
    #         nml['initialconditions']['albEveTr0'] = 0.10
    #         nml['initialconditions']['albDecTr0'] = 0.12
    #         nml['initialconditions']['albGrass0'] = 0.18
    #         nml['initialconditions']['decidCap0'] = 0.3
    #         nml['initialconditions']['porosity0'] = 0.2
    #     elif LeafCycle == 2:
    #         nml['initialconditions']['gdd_1_0'] = 50
    #         nml['initialconditions']['gdd_2_0'] = -400
    #         nml['initialconditions']['laiinitialevetr'] = 4.2
    #         nml['initialconditions']['laiinitialdectr'] = 2.0
    #         nml['initialconditions']['laiinitialgrass'] = 2.6
    #         nml['initialconditions']['albEveTr0'] = 0.10
    #         nml['initialconditions']['albDecTr0'] = 0.12
    #         nml['initialconditions']['albGrass0'] = 0.18
    #         nml['initialconditions']['decidCap0'] = 0.4
    #         nml['initialconditions']['porosity0'] = 0.3
    #     elif LeafCycle == 3:
    #         nml['initialconditions']['gdd_1_0'] = 150
    #         nml['initialconditions']['gdd_2_0'] = -300
    #         nml['initialconditions']['laiinitialevetr'] = 4.6
    #         nml['initialconditions']['laiinitialdectr'] = 3.0
    #         nml['initialconditions']['laiinitialgrass'] = 3.6
    #         nml['initialconditions']['albEveTr0'] = 0.10
    #         nml['initialconditions']['albDecTr0'] = 0.12
    #         nml['initialconditions']['albGrass0'] = 0.18
    #         nml['initialconditions']['decidCap0'] = 0.6
    #         nml['initialconditions']['porosity0'] = 0.5
    #     elif LeafCycle == 4:
    #         nml['initialconditions']['gdd_1_0'] = 225
    #         nml['initialconditions']['gdd_2_0'] = -150
    #         nml['initialconditions']['laiinitialevetr'] = 4.9
    #         nml['initialconditions']['laiinitialdectr'] = 4.5
    #         nml['initialconditions']['laiinitialgrass'] = 4.6
    #         nml['initialconditions']['albEveTr0'] = 0.10
    #         nml['initialconditions']['albDecTr0'] = 0.12
    #         nml['initialconditions']['albGrass0'] = 0.18
    #         nml['initialconditions']['decidCap0'] = 0.8
    #         nml['initialconditions']['porosity0'] = 0.6
    #     elif LeafCycle == 5:  # Summer
    #         nml['initialconditions']['gdd_1_0'] = 300
    #         nml['initialconditions']['gdd_2_0'] = 0
    #         nml['initialconditions']['laiinitialevetr'] = 5.1
    #         nml['initialconditions']['laiinitialdectr'] = 5.5
    #         nml['initialconditions']['laiinitialgrass'] = 5.9
    #         nml['initialconditions']['albEveTr0'] = 0.10
    #         nml['initialconditions']['albDecTr0'] = 0.12
    #         nml['initialconditions']['albGrass0'] = 0.18
    #         nml['initialconditions']['decidCap0'] = 0.8
    #         nml['initialconditions']['porosity0'] = 0.6
    #     elif LeafCycle == 6:
    #         nml['initialconditions']['gdd_1_0'] = 225
    #         nml['initialconditions']['gdd_2_0'] = -150
    #         nml['initialconditions']['laiinitialevetr'] = 4.9
    #         nml['initialconditions']['laiinitialdectr'] = 4, 5
    #         nml['initialconditions']['laiinitialgrass'] = 4.6
    #         nml['initialconditions']['albEveTr0'] = 0.10
    #         nml['initialconditions']['albDecTr0'] = 0.12
    #         nml['initialconditions']['albGrass0'] = 0.18
    #         nml['initialconditions']['decidCap0'] = 0.8
    #         nml['initialconditions']['porosity0'] = 0.5
    #     elif LeafCycle == 7:
    #         nml['initialconditions']['gdd_1_0'] = 150
    #         nml['initialconditions']['gdd_2_0'] = -300
    #         nml['initialconditions']['laiinitialevetr'] = 4.6
    #         nml['initialconditions']['laiinitialdectr'] = 3.0
    #         nml['initialconditions']['laiinitialgrass'] = 3.6
    #         nml['initialconditions']['albEveTr0'] = 0.10
    #         nml['initialconditions']['albDecTr0'] = 0.12
    #         nml['initialconditions']['albGrass0'] = 0.18
    #         nml['initialconditions']['decidCap0'] = 0.5
    #         nml['initialconditions']['porosity0'] = 0.4
    #     elif LeafCycle == 8:  # Late Autumn
    #         nml['initialconditions']['gdd_1_0'] = 50
    #         nml['initialconditions']['gdd_2_0'] = -400
    #         nml['initialconditions']['laiinitialevetr'] = 4.2
    #         nml['initialconditions']['laiinitialdectr'] = 2.0
    #         nml['initialconditions']['laiinitialgrass'] = 2.6
    #         nml['initialconditions']['albEveTr0'] = 0.10
    #         nml['initialconditions']['albDecTr0'] = 0.12
    #         nml['initialconditions']['albGrass0'] = 0.18
    #         nml['initialconditions']['decidCap0'] = 0.4
    #         nml['initialconditions']['porosity0'] = 0.2

    #     nml['initialconditions']['snowinitially'] = snowinitially

    #     nml.write(initfileout, force=True)


    def progress_update(self):
        self.steps += 1
        self.dlg.progressBar.setValue(self.steps)


## unused functions
# def hide_show_LCF(self, widget):
    #     if widget.LCF_checkBox.isChecked():
    #         self.LCF_from_file = False
    #         widget.LCF_Frame.show()
    #         widget.pushButtonImportLCF.hide()
    #         widget.textInputLCFData.hide()
    #     else:
    #         self.LCF_from_file = True
    #         widget.LCF_Frame.hide()
    #         widget.pushButtonImportLCF.show()
    #         widget.textInputLCFData.show()

    # def hide_show_IMP(self, widget):
    #     if widget.IMP_checkBox.isChecked():
    #         self.IMP_from_file = False
    #         widget.IMP_Frame.show()
    #         widget.pushButtonImportIMPBuild.hide()
    #         widget.textInputIMPData.hide()
    #     else:
    #         self.IMP_from_file = True
    #         widget.IMP_Frame.hide()
    #         widget.pushButtonImportIMPBuild.show()
    #         widget.textInputIMPData.show()

    # def hide_show_IMPveg(self, widget):
    #     if widget.IMPveg_checkBox.isChecked():
    #         self.IMPveg_from_file = False
    #         widget.IMPveg_Frame.show()
    #         widget.pushButtonImportIMPVeg.hide()
    #         widget.textInputIMPVegData.hide()
    #         widget.checkBox_twovegfiles.hide()
    #         widget.pushButtonImportIMPVeg_eve.hide()
    #         widget.pushButtonImportIMPVeg_dec.hide()
    #         widget.textInputIMPEveData.hide()
    #         widget.textInputIMPDecData.hide()
    #     else:
    #         self.IMPveg_from_file = True
    #         widget.IMPveg_Frame.hide()
    #         widget.pushButtonImportIMPVeg.show()
    #         widget.textInputIMPVegData.show()
    #         widget.checkBox_twovegfiles.show()
    #         widget.pushButtonImportIMPVeg_eve.show()
    #         widget.pushButtonImportIMPVeg_dec.show()
    #         widget.textInputIMPEveData.show()
    #         widget.textInputIMPDecData.show()

    # def grid_layer_changed(self, widget, timezone):

    #     # Try to avoid error when no gridlayer present, or layers added or removed to project
    #     try:
    #         poly = self.layerComboManagerPolygrid.currentLayer()
    #         grid_path = poly.source()
    #         utc = get_utc(grid_path, timezone)
    #         widget.lineEditUTC.setText(str(utc))
    #     except:
    #         pass


