﻿# Tämä laskentakoodi perustuu KEKO ekolaskuriin. 
# SYKEn internet-sivulla olevan KEKO ekolaskurin osoite on www.ymparisto.fi/keko 
# Tätä viittausta KEKOon ja SYKEen internet-sivun osoitetta ei saa poistaa koodin alusta 
# vaikka koodia muokattaisiin.
# @ author Maija Mattinen, SYKE, 2015
# -*- coding: utf-8 -*-
#
# # Tämä laskentakoodi perustuu KEKO ekolaskuriin. 
# SYKEn internet-sivulla olevan KEKO ekolaskurin osoite on www.ymparisto.fi/keko 
# Tätä viittausta KEKOon ja SYKEen internet-sivun osoitetta ei saa poistaa koodin alusta 
# vaikka koodia muokattaisiin.
# Import needed constants and the numpy package
import numpy
from numpy import *
from KEKOResultConstant import *
def CalcKEKOresult(lahtotiedotS11, lahtotiedotC11, lahtotiedotC10,
                lahtotiedotE11,lahtotiedotE10,
                lahtotiedotM11, lahtotiedotM10,ghg_outputs,
                material_outputs, natureIndex, userFloorAreas,
                userBuiltAreas, ghg_landUse, ghg_constB,
                ghg_Bmaint, ghg_BeneEm, eneAllSum,
                sumTot1Sum, matLandSumTot, renewableTotSum,
                nonRenewableTotSum, ghg_infra, ghg_transport,
                mat_BuildingTot, mat_InfraTot):
    ###### This is the topmost function in the hierarchy that calls other functions ######
    ###### and returns the final outputs
    ave_pop = CalcAve(lahtotiedotS11, lahtotiedotC11, lahtotiedotC10) # Excel:J10
    ave_work = CalcAve(lahtotiedotS11, lahtotiedotE11, lahtotiedotE10) # Excel:J11
    ave_floorarea = CalcAve(lahtotiedotS11, lahtotiedotM11, lahtotiedotM10) # Excel:J12
    ghg_output = sum(ghg_outputs) # sum up the ghg outputs
    material_output = sum(material_outputs) # sum up the material output
    indices = CalcEcoIndex(ghg_output, ave_floorarea, material_output,
                           natureIndex) # Calculate indices, Excel: H62-H65
    if(ave_floorarea > 0): # make sure not dividing by zero
        ghgPerFloorarea = ghg_output / ave_floorarea
        materialPerFloorarea = material_output / ave_floorarea
    else:
        ghgPerFloorarea = 0
        materialPerFloorarea = 0
    areaSpecs = CalcAreaInfo(userFloorAreas, userBuiltAreas,
                 lahtotiedotC11, lahtotiedotE11)
    if(ave_pop > 0): # make sure not dividing by zero
        ghgPerPerson = ghg_output / ave_pop
        materialPerPerson = material_output /ave_pop
    else:
        ghgPerPerson = 0
        materialPerPerson = 0
    # Calculate emission details
    # per pop
    emDetailsPerPop = CalcEmissionDetailsPerPop(ghg_landUse, ghg_infra,
                                    ave_pop,
                                    ghg_constB, ghg_Bmaint, ghg_BeneEm,
                                    ghg_transport)
    # per floor area
    emDetailsPerfloorarea = CalcEmissionDetailsPerFloorArea(ghg_landUse,
                                    ghg_infra, ave_floorarea,
                                    ghg_constB, ghg_Bmaint, ghg_BeneEm,
                                    ghg_transport)
    # Building construction and maintenance
    ghg_Building = ghg_constB + ghg_Bmaint # Excel: G141
    # Sums for building energy consumption
    eneSum = sum(eneAllSum, axis = 1)
    ## Material
    # Building
    mat_building = CalcMatBuilding(mat_BuildingTot, ave_pop, ave_floorarea)
    # Infra
    pop_change = lahtotiedotC11 - lahtotiedotC10
    floor_change = lahtotiedotM11- lahtotiedotM10 
    mat_infra = CalcMatInfra(mat_InfraTot, pop_change, floor_change)
    # Collate output
    output_fin = []
    output_fin.append(ave_pop) # output [0] Excel: J10
    output_fin.append(ave_work) # output [1] Excel: J11
    output_fin.append(ave_floorarea) # output [2] Excel: J12
    output_fin.append(ghg_output) # output [3] Excel: J13
    output_fin.append(material_output) # output [4] Excel: J14
    output_fin.append(indices) # output [5] Excel: H62-H65
    output_fin.append(ghgPerFloorarea) # output [6] Excel: H91
    output_fin.append(areaSpecs) # output [7] Excel: H48:H50
    output_fin.append(ghgPerPerson) # output [8] Excel: H95
    output_fin.append(materialPerPerson) # output[9] Excel: H98
    output_fin.append(materialPerFloorarea) # output[10] Excel: H99
    output_fin.append(emDetailsPerPop) # output[11] Excel: G113-G118
    output_fin.append(eneSum) # output[12]
    output_fin.append(emDetailsPerfloorarea) # output[13] Excel: G133-G138
    output_fin.append(ghg_Building) # output[14] Excel: G141
    output_fin.append(mat_building) # output[15] Excel: G144, G145
    output_fin.append(mat_infra) # output[16] Excel: G148, G149
    return output_fin

##############################################################################
###### The following functions are called by the function "CalcKEKOresult" #######
##############################################################################
def CalcMatBuilding(mat_BuildingTot, ave_pop, ave_floorarea):
    # Rakennusten materiaalien kulutus
    if (ave_pop > 0): # make sure not dividing by zero
        mat_BuildingPerPop = mat_BuildingTot / ave_pop
    else:
        matBuildingPerPop = 0
    if (ave_floorarea > 0): # make sure not dividing by zero
        mat_BuildingPerFloorarea = mat_BuildingTot / ave_floorarea
    else:
        mat_BuildingPerFloorarea = 0
    matBuilding = [mat_BuildingPerPop, mat_BuildingPerFloorarea]
    return matBuilding

def CalcMatInfra(mat_InfraTot, pop_change, floor_change):
    # Rakennusten materiaalien kulutus
    if(pop_change >0): # make sure not dividing by zero
        mat_InfraPerPopChange = mat_InfraTot / pop_change
    else:
        mat_InfraPerPopChange = 0
    if(floor_change > 0): # make sure not dividing by zero
        mat_InfraPerFloorChange = mat_InfraTot / floor_change
    else:
        mat_InfraPerFloorChange = 0
    matInfra = [mat_InfraPerPopChange, mat_InfraPerFloorChange]
    return matInfra

def CalcEmissionDetailsPerFloorArea(ghg_landUse, ghg_infra, ave_floorarea, ghg_constB,
                        ghg_Bmaint, ghg_BeneEm, ghg_transport):
    # All in [CO2 t/ m2]
    # Construction of buildings + maintenance
    divisor = ave_floorarea
    if(divisor > 0): # make sure not dividing by zero
        ghg_landUsePerfloorarea = ghg_landUse / divisor # G133
        ghg_infraPerfloorarea = ghg_infra / divisor # G134
        ghg_BuildConstMaintPerfloorarea = (ghg_constB + ghg_Bmaint)/divisor # G135
        ghg_BeneEmPerfloorarea = ghg_BeneEm / divisor # G136
        ghg_transportPerfloorarea = ghg_transport / divisor # G137
    else:
        ghg_landUsePerfloorarea = 0
        ghg_infraPerfloorarea = 0
        ghg_BuildConstMaintPerfloorarea = 0
        ghg_BeneEmPerfloorarea = array([0])#0
        ghg_transportPerfloorarea = 0
    emDetails2 = array([ghg_landUsePerfloorarea, ghg_infraPerfloorarea,
                       ghg_BuildConstMaintPerfloorarea, ghg_BeneEmPerfloorarea[0],
                       ghg_transportPerfloorarea])
    ghg_totPerfloorarea = sum(emDetails2) # G138
    return [emDetails2, ghg_totPerfloorarea]#, emDetailsPerYear]

def CalcEmissionDetailsPerPop(ghg_landUse, ghg_infra, ave_pop, ghg_constB,
                        ghg_Bmaint, ghg_BeneEm, ghg_transport):
    # All in [CO2 t/ person]
    # Construction of buildings + maintenance
    divisor = ave_pop
    if(divisor > 0): # make sure not dividing by zero
        ghg_landUsePerPop = ghg_landUse / divisor # G113
        ghg_infraPerPop = ghg_infra / divisor # G114
        ghg_BuildConstMaintPerPop = (ghg_constB + ghg_Bmaint)/divisor # G115
        ghg_BeneEmPerPop = ghg_BeneEm / divisor # G116
        ghg_transportPerPop = ghg_transport / divisor # G117
    else:
        ghg_landUsePerPop = 0
        ghg_infraPerPop = 0
        ghg_BuildConstMaintPerPop = 0
        ghg_BeneEmPerPop = 0
        ghg_transportPerPop = 0
    emDetails = array([ghg_landUsePerPop, ghg_infraPerPop,
                       ghg_BuildConstMaintPerPop, ghg_BeneEmPerPop[0],
                       ghg_transportPerPop])
    ghg_totPerPop = sum(emDetails) # G118
    return [emDetails, ghg_totPerPop]

def CalcAreaInfo(userFloorAreas, userBuiltAreas,
                 lahtotiedotC11, lahtotiedotE11):
    # Calculates area density, asukastiheys, työpaikkatiheys
    # TULOSSIVU: H48:H50
    # Aluetehokkuus H48
    sum_floor = sum(userFloorAreas,axis = 1)
    sum_area = sum(userBuiltAreas, axis = 1)
    areaDensity = sum_floor / (sum_area * 10000) # Lähtötiedot L30,M30
    if(sum_area[1] > 0): # make sure not dividing by zero
        popDensity = lahtotiedotC11 / sum_area[1] # H49
        workpDensity = lahtotiedotE11 / sum_area[1] # H50
    else:
        popDensity = 0
        workpDensity = 0
    areaSpecs = [areaDensity[1], popDensity, workpDensity]
    return areaSpecs

def CalcAve(lahtotiedotS11, lahtotiedotC11, lahtotiedotC10):
    # J10 or J11
    part1 = array([lahtotiedotC11,lahtotiedotC10])
    part2 = (lahtotiedotS11 * average(part1, axis=0) +\
              (50 - lahtotiedotS11) * lahtotiedotC11) / 50
    output = part2
    return output

def CalcEcoIndex(ghg_output, ave_floorarea, material_output, natureIndex):
    # CO2
    if(ave_floorarea > 0):
        index1 = 100 * ghg_output/ ave_floorarea / C_co2
        index2 = 100 * material_output / ave_floorarea / sum(C_materials)
    else:
        index1 = 0
        index2 = 0
    indices = [index1, index2, natureIndex]
    ave_index = average(indices)
    indexOutput = [indices, ave_index]
    return indexOutput

# @ author Maija Mattinen, SYKE, 2015
# -*- coding: utf-8 -*-
#
# Tämä laskentakoodi perustuu KEKO ekolaskuriin. 
# SYKEn internet-sivulla olevan KEKO ekolaskurin osoite on www.ymparisto.fi/keko 
# Tätä viittausta KEKOon ja SYKEen internet-sivun osoitetta ei saa poistaa koodin alusta 
# vaikka koodia muokattaisiin.
# Import needed constants and the numpy package
import numpy
from numpy import *
from KEKOBuildingConstant import *

def CalcBuilding(userFoundTypeShares, userNfloors,
                 userFloorAreas, userBuildingShares,
                 userEnergyConsumptions, userBuildingTime,
                 userPopulation, userWorkPlaces, userFloorAreas2):
    ###### This is the topmost function in the hierarchy that calls other functions ######
    ###### and returns the final outputs for the UI
    # Areas of new stock:
    userNewShare = userBuildingShares[:,0] # E7:E14
    areaNew = userFloorAreas * userNewShare # D318:D325
    # Rakentaminen, luonnonvarat, rows 134:141
    constMatOutput = CalcMatBuildings(userFoundTypeShares, userNfloors,
                                 userFloorAreas, userNewShare, areaNew)
    materialsElements = CalcMatElements(areaNew, userBuildingShares,
                                constMatOutput)
    altErepOutput = CalcAlterationEneRep(userFloorAreas,
                                         userBuildingShares)
    repAreas = altErepOutput[2]
    newAreas = altErepOutput[3]
    # calculate material
    matSums = SumMaterials(materialsElements, altErepOutput)
    # Start emission calculations
    emOutput = CalcEmissions(userBuildingShares, userFoundTypeShares,
                             areaNew, repAreas, newAreas)
    changes = CalcStockChange(userFloorAreas,userBuildingShares)
    stockYear = changes[2]
    oldOther = changes[3]
    sumAreas = areaNew + repAreas + newAreas
    # Start energy consumption calculations
    eneOutput = CalcEneConsAll(repAreas, areaNew,
                    stockYear, userEnergyConsumptions, oldOther,
                    userBuildingShares, newAreas)
    emYears = CalcEmYears(userPopulation, userWorkPlaces,
                          userBuildingTime, userFloorAreas2, emOutput,
                          stockYear, sumAreas)
    ## ----Select the outputs ## 
    # OUTPUTS
    output = []# constMatOutput#
    output.append(matSums) # 0
    output.append(emOutput) # 1
    output.append(eneOutput) # 2
    output.append(emYears) # 3 
    return output

##############################################################################
###### The following functions are called by the function "CalcBuilding" #######
##############################################################################
def CalcMaintEmYears(stockYear, sumAreas, userBuildingTime):
    # rakennusten kunnossapito, päästöt
    # D495:BB510
    # old stock
    # sumstock Year first
    stockYearSum = sum(stockYear, axis = 0) # F318:F325
    oldAll = []
    newAll = []
    # uusien päästöt aloitetaan vasta kun rakennusajasta kulunut puolet!
    # sen jälkeen otetaan kunnossapidon päästöt vuosittain
    # YEAR[buildingTime/2] = "year 1"
    newStartY = floor(userBuildingTime / 2)
    newEndY = n_calcYears - newStartY + 1
    for hType in range(nBtypes):
        if hType == 0:
            cDummy = 0
        if hType > 0 and hType < 3:
            cDummy = 1
        if hType > 2 and hType < 5:
            cDummy = 2
        if hType == 5:
            cDummy = 3
        if hType >5:
            cDummy = 2
        cRow = CbuildingMaintenance[:,cDummy]
        cRow2 = zeros(51) # check
        cRow2[newStartY:50] = CbuildingMaintenance[1:newEndY,cDummy]
        oldAll.append(stockYearSum[hType] * cRow)
        newAll.append(sumAreas[hType] * cRow2)
    # sum
    oldAllSum = sum(oldAll, axis = 0)
    newAllSum = sum(newAll, axis = 0)
    maintAllSum = oldAllSum + newAllSum # output[0], [1x51]
    maintAllSumCum = cumsum(maintAllSum, axis = 0) # output[1], [1x51]
    maintEmOutput = [maintAllSum, maintAllSumCum]
    # output[0], maintAllSum = [1x51] [tCO2], row 518
    # output[1], maintAllSumCum = [1x51], [tCO2], row 519
    return maintEmOutput

def CalcEmYears(userPopulation, userWorkPlaces, userBuildingTime,
                userFloorArea2, emAll, stockYear, sumAreas):
    # Split and re-arrange some input
    emSumAll = []
    emSumAll.append(emAll[1]) # newStockEmSum
    emSumAll.append(emAll[5]) # altEmSum 
    emSumAll.append(emAll[3]) # enReEmSum
    # Population growth row 417
    delta_popWork = (userPopulation[1] + userWorkPlaces[1]) -\
                      (userPopulation[0] + userWorkPlaces[0])
    extra_popWork = delta_popWork / userBuildingTime
    popWork_all = zeros(n_calcYears +1) # initialize
    popWork_all[0] = userPopulation[0] + userWorkPlaces[0]
    popWork_all[1:userBuildingTime+1] = extra_popWork
    popWork_all_cum = cumsum(popWork_all) #
    # Floor area growth, row 419
    delta_floorA = userFloorArea2[1] - userFloorArea2[0]
    if (userBuildingTime > 0):
        extra_floorA = delta_floorA / userBuildingTime
    else:
        extra_floorA = 0
    floorA_all = zeros(n_calcYears +1) # initialize
    floorA_all[0] = userFloorArea2[0]
    floorA_all[1:userBuildingTime+1] = extra_floorA
    floorA_all_cum = cumsum(floorA_all) #
    # building construction, annual emissions E422:BB424
    constEmAllCum = []
    constEmAll = []
    for tInde in range(3):
        if (userBuildingTime > 0):
            extraDummy = emSumAll[tInde] / userBuildingTime
        else:
            extraDummy = 0
        varDummy = zeros(n_calcYears+1)
        varDummy[1:userBuildingTime+1] = extraDummy
        constEmAll.append(varDummy)
        varDummyCum = cumsum(varDummy)
        constEmAllCum.append(varDummyCum) # 3 x[1x51]
    # Sum construction emissions
    constEmAllCumSum = sum(constEmAllCum, axis = 0) # row 516
    constEmAllSum = sum(constEmAll, axis = 0) # row 517
# maintenance
    maintEmY = CalcMaintEmYears(stockYear, sumAreas, userBuildingTime)
    maintAllSum = maintEmY[0]
    maintAllSumCum = maintEmY[1]
    emYearsOutput = [popWork_all_cum, floorA_all_cum, constEmAllCumSum,
                     constEmAllSum, maintAllSum, maintAllSumCum]
    # output[0] = popWork_all_cum = [1x51], row 417
    # output[1] = floorA_all_cum = [1x51], row 419
    # output[2] = constEmAllCumSum = [1x51], row 516
    # output[3] = constEmAllSum = [1x51], row 517
    # output[4] = maintAllSum = [1x51], row518
    # output[5] = maintAllSumCum = [1x51], row 519
    return emYearsOutput


def SumMaterials(matElementsAll, matAltErepAll):
    # Split the input first
    # Elements (Rakenneosat)
    # mat1 = okt, rt
    # mat2 = maaosat,pohjarakenteet for the rest of bTypes
    # mat3 = all the rest
    matElem1 = matElementsAll[0]
    matElem2 = matElementsAll[1]
    matElem3 = matElementsAll[2]
    # energy repairing
    matErepAll = matAltErepAll[0]
    # Alteration
    matAltAll = matAltErepAll[1]
    # Renewable
    renElements = matElementsAll[3]
    renAlt = matAltErepAll[4]
    renRep = matAltErepAll[5]
    # sum detached and detached houses (okt ja rt)
    # initialize
    matSum1 = zeros(([nR2,nC2])) # 24x3 okt
    matSum2 = zeros(([nR2,nC2])) # 34 x3 rt
    # calculate
    matSum1[0:4,:] = matElem1[0][0:4,:] # detached 4 first rows
    matSum2[0:4,:] = matElem1[1][0:4,:] # attached 4 first rows
    # elements+energy rep+alteration
    matSum1[4:,:] = matElem1[0][4:,:] + matErepAll[0] + matAltAll[0]
    matSum2[4:,:] = matElem1[1][4:,:] + matErepAll[1] + matAltAll[1]
    # Handle rest of the building types
    matSumRest = [] # init
    for hType in range(nBtypesR): # loop house types
        sumDummy = zeros(([nR2,nC2])) # initialize dummy variable
        # 4 first rows from matElem2
        for d in range(3): # loop rungot
            if hType == 0 and d == 0:
                dummy = 0
            if matElem2[dummy] == []: # if empty, put zeros
                row = zeros(4)
            else:
                row = matElem2[dummy] # else take from element input
            row2 = matElem3[dummy] # rest of the rows...
            sumDummy[0:4,d] = row
            sumDummy[4:,d] = row2
            dummy += 1 # increase dummy
        matSumRest.append(sumDummy) # save
        # Then sum the rest of the rows (elements+energy rep+alteration)
        matSumRest[hType][4:,:] += matErepAll[hType] + matAltAll[hType]
    # collate output
    matSums = []
    matSums.append(matSum1) # 0 okt, [24x3], F268:H291
    matSums.append(matSum2) # 1 rt, [24x3], I268:K291
    matSums.append(matSumRest) # 2 rest, 6 x[24x3], L268:AC291
    # SUMS
    # Total
    sumTot1 = [] # tot, [t], row 292
    matLandSum = [] # maaosat row 293
    sumTot2 = [] # rungoittain tot [t], AD-AF
    # detached house
    sumTot1.append(sum(matSums[0],axis = 0)) # okt
    matLandSum.append(sum(matSums[0][0:2,:], axis = 0))
    sumTot2 = matSums[0] + matSums[1]
    # attached house
    sumTot1.append(sum(matSums[1],axis = 0)) # rt
    matLandSum.append(sum(matSums[1][0:2,:], axis = 0))
    for inde in range(nBtypesR): # rest
        var = matSums[2][inde]
        sumTot1.append(sum(var,axis=0))
        matLandSum.append(sum(var[0:2,:],axis = 0))
        sumTot2 += var
    # uusiutuvat row 294
    # renewableAll + renAlt + renRep
    renewableTot = []
    nonRenewableTot = []
    for hInde in range(nBtypes):
        renewableTot.append(renElements[hInde] + \
                        renAlt[hInde] + renRep[hInde])
        # uusiutumattomat row 295
        nonRenewableTot.append(sumTot1[hInde] - \
                    matLandSum[hInde]-renewableTot[hInde])
    sumTot1Sum = sum(sumTot1, axis = 0)
    matLandSumTot = sum(matLandSum, axis = 0)
    renewableTotSum = sum(renewableTot, axis = 0)
    nonRenewableTotSum = sum(nonRenewableTot, axis = 0)
    # FINAL AGGREGATES...
    renSumFin = sum(renewableTotSum) # D437
    nonRenSumFin = sum(nonRenewableTotSum) # D432
    matLandSumFin = sum(matLandSumTot) # D442
    totFin = renSumFin + nonRenSumFin + matLandSumFin # D443
    matSumOutput = [matSums, sumTot1, matLandSum, sumTot2,
                    renewableTot, nonRenewableTot, sumTot1Sum,
                    matLandSumTot, renewableTotSum, nonRenewableTotSum,
                    renSumFin, nonRenSumFin, matLandSumFin,
                    totFin]
    # output[0] = matSums
    # output[1] = sumTot1 = 8x [1x3] (row292)
    # output[2] = matLandSum= 8x [1x3] (row 293)
    # output[3] = sumTot2 = 24 x 3 (AD268:AF291)
    # output[4] = renewableTot = 8 x [1x3] (row 294)
    # output[5] = nonRenewableTot = 8 x[1x3] (row 295)
    # output[6] = sumTot1Sum = [1x3], AD292:AF292
    # output[7] = matLandSumTot = [1x3], AD293:AF293
    # output[8] = renewableTotSum = [1x3], AD294:AF294
    # output[9] = nonRenewableTotSum = [1x3], AD295:AF295
    # output[10] = renSumFin = [1x1], [t] D437
    # output[11] = nonRenSumFin = [1x1], [t], D432
    # output[12] = matLandSumFin = [1x1], [t], D442
    # output[13] = totFin = [1x1], [t], D443
    return matSumOutput


def CalcEneConsAll(repAreas, areaNew, stockYear, userEnergyConsumptions, oldOther,
               userBuildingShares, newAreas):
    # Call the calculation functions
    # after construction
    eneOutput = CalcEneConsumption(stockYear, userEnergyConsumptions,
                                   oldOther, userBuildingShares)
    # New stock
    eneOutputNewStock = CalcEneConsNewStock(areaNew, userBuildingShares,
                              userEnergyConsumptions)
    # Energy repairing
    eneOutputErepStock = CalcEneConsERepStock(repAreas, userBuildingShares,
                                              userEnergyConsumptions)
    # Alteration of use
    eneOutputAlt = CalcEneConsAlt(newAreas, userEnergyConsumptions)
    # init
    eneInput2 = []
    eneAllSum = []
    for index in range(nEne):
        # input for energy calculations I396:M403
        eneInput2.append(eneOutputNewStock[index] + eneOutputErepStock[index] \
                  + eneOutputAlt[index])
        # sum (column R)
        eneAllSum.append(eneOutput[index] + eneInput2[index])
    # Calculate shares (row 548)
    eneAllSum2 = sum(eneAllSum, axis = 1) # sums, row 547
    eneAllSum2All = sum(eneAllSum2) # total sum
    # shares:
    eneShares = []
    for inde2 in range(nEne):
        if(eneAllSum2All > 0):
            eneShares.append(eneAllSum2[inde2] / eneAllSum2All)
        else:
            eneShares.append(0)
    # collate outputs
    # eneCons[0] = eneOutput, 4x [1x8], D396:G403, [kWh]
    # eneCons[1] = eneInput2, 4 x [1x8], I396:M403, [kWh]
    # eneCons[2] = eneAllSum, [kWh] 4 x [1x8],
    # R346:R353& R359:R366& R372:R379& R385:R392
    # eneCons[3] = eneShares, [1x4], E548:H548, [%]
    eneCons = [eneOutput, eneInput2, eneAllSum, eneShares]
    return eneCons

def CalcEneConsAlt(newAreas, userEnergyConsumptions):
    # käyttötavan muutos, 2013 normitaso
    # Q346:Q353 jne.
    # heating
    Cheating4 = zeros(nBtypes)
    Cheating4[0:7] = CheatingBtypesYears[:,7]
    Cheating4[7] = userEnergyConsumptions[0,7]
    heating4 = newAreas * Cheating4
    #hotwater
    hotwater4 = newAreas * CheatingWBtypesYears[:,7]
    # electricity
    Cele4 = zeros(nBtypes)
    Cele4[0:7] = CelectricityBtypesYears[:,7]
    Cele4[7] = userEnergyConsumptions[1,7]
    ele4 = newAreas * Cele4
    # cooling
    Ccooling4 = zeros(nBtypes)
    Ccooling4[0:7] = CcoolingBtypesYears[:,7]
    Ccooling4[7] = userEnergyConsumptions[2,7]
    cooling4 = newAreas * Ccooling4
    # [1x8]
    altOutput = [heating4, hotwater4, ele4,
                cooling4]
    return altOutput

def CalcEneConsERepStock(repAreas, userBuildingShares, userEnergyConsumptions):
    # energiakorjatut rakennukset
    # lämpö
    heating3 = []
    Cheating3 = zeros(([nBtypes,nC2])) #init
    Cheating3[0:7,:] = CheatingBtypesYears[:,7:10]
    Cheating3[7,:] = userEnergyConsumptions[0,7:10]
    Cheating3Fin = Cheating3 * userBuildingShares[:,15:18]
    # hotwater
    hotwater3 = []
    Chotwater3Fin = CheatingWBtypesYears[:,7:10] * userBuildingShares[:,15:18]
    # electricity
    ele3 = []
    Cele3 = zeros(([nBtypes,nC2]))
    Cele3[0:7,:] = CelectricityBtypesYears[:,7:10]
    Cele3[7,:] = userEnergyConsumptions[1,7:10]
    Cele3Fin = Cele3 * userBuildingShares[:,15:18]
    # cooling
    cooling3 = []
    Ccooling3 = zeros(([nBtypes,nC2]))
    Ccooling3[0:7,:] = CcoolingBtypesYears[:,7:10]
    Ccooling3[7,:] = userEnergyConsumptions[2,7:10]
    Ccooling3Fin = Ccooling3 * userBuildingShares[:,15:18]
    for yClass in range(nC2):#loop each year class
        # tallennus 3 x [1x8] muodossa, eli vuosittain
        heating3.append(repAreas * Cheating3Fin[:,yClass])
        hotwater3.append(repAreas * Chotwater3Fin[:,yClass])
        ele3.append(repAreas * Cele3Fin[:,yClass])
        cooling3.append(repAreas * Ccooling3Fin[:,yClass])
    # SUMs[1x8] inputs for energy.py
    heating3SUM = sum(heating3, axis = 0) # 0, 
    hotWater3SUM = sum(hotwater3, axis = 0)# 1, 
    electricity3SUM = sum(ele3, axis = 0) # 2,
    cooling3SUM = sum(cooling3, axis = 0) # 3, 
    consErep = [heating3SUM, hotWater3SUM, electricity3SUM,
                cooling3SUM]
    return consErep

def CalcEneConsNewStock(areaNew, userBuildingShares, userEnergyConsumptions):
    # new buildings
    # Lämpö K346:M353
    heating2 = []
    Cheating2 = zeros(([nBtypes,nC2]))
    Cheating2[0:7,:] = CheatingBtypesYears[:,7:10]
    Cheating2[7,:] = userEnergyConsumptions[0,7:10]
    Cheating2Fin = Cheating2 * userBuildingShares[:,9:12]
    # Hot water K359:M366
    hotwater2 = []
    ChotWater2Fin = CheatingWBtypesYears[:,7:10] * userBuildingShares[:,9:12]
    # Electricity
    ele2 = []
    Cele2 = zeros(([nBtypes,nC2]))
    Cele2[0:7,:] = CelectricityBtypesYears[:,7:10]
    Cele2[7,:] = userEnergyConsumptions[1,7:10]
    Cele2Fin = Cele2 * userBuildingShares[:,9:12]
    # cooling
    cooling2 = []
    Ccooling2 = zeros(([nBtypes,nC2]))
    Ccooling2[0:7,:] = CcoolingBtypesYears[:,7:10]
    Ccooling2[7,:] = userEnergyConsumptions[2,7:10]
    Ccooling2Fin = Ccooling2 * userBuildingShares[:,9:12]
    for yClass in range(nC2):#loop each year class
        # save in 3 x [1x8] format, annually
        heating2.append(areaNew * Cheating2Fin[:,yClass])
        hotwater2.append(areaNew * ChotWater2Fin[:,yClass])
        ele2.append(areaNew * Cele2Fin[:,yClass])
        cooling2.append(areaNew * Ccooling2Fin[:,yClass])
    # SUMs[1x8] inputs for energy.py
    heating2SUM = sum(heating2, axis = 0) # 0, 
    hotWater2SUM = sum(hotwater2, axis = 0)# 1, 
    electricity2SUM = sum(ele2, axis = 0) # 2,
    cooling2SUM = sum(cooling2, axis = 0) # 3, 
    eConsOutput = [heating2SUM, hotWater2SUM, electricity2SUM,
                   cooling2SUM]
    return eConsOutput

def CalcEneConsumption(stockYear, userEnergyConsumptions, oldOther,
                       userBuildingShares):
    heating = []
    Cheating = zeros(([nBtypes,nC]))
    Cheating[0:7,:] = CheatingBtypesYears[:,0:7]
    Cheating[7,:] = userEnergyConsumptions[0,0:7]
    # LKV D359:J366
    hotWater = []
    ChotWater = CheatingWBtypesYears#CeneAll[1]
    # Electricity D372:J379
    # yhdistä ensin user input vakiokertoimien kanssa..
    electricity = []
    Celectricity = zeros(([nBtypes,nC]))
    Celectricity[0:7,:] = CelectricityBtypesYears[:,0:7]
    Celectricity[7,:] = userEnergyConsumptions[1,0:7]
    # Cooling D385:J392
    cooling = []
    Ccooling = zeros(([nBtypes,nC]))
    Ccooling[0:7,:] = CcoolingBtypesYears[:,0:7]
    Ccooling[7,:] = userEnergyConsumptions[2,0:7]
    # For fixing the heating of other buildings
    other1 = userBuildingShares[7,2:9] * userEnergyConsumptions[0,0:7]
    other2 = userBuildingShares[7,2:9] * ChotWater[7,0:7]
    other3 = userBuildingShares[7,2:9] * Celectricity[7,0:7]
    other4 = userBuildingShares[7,2:9] * Ccooling[7,0:7]
    heatingOther = oldOther * other1
    hotWaterOther = oldOther * other2
    electricityOther = oldOther * other3
    coolingOther = oldOther * other4
    for yClass in range(nC):#loop each year class
        # tallennus 7 x [1x8] muodossa, eli vuosittain
        heating.append(stockYear[yClass] * Cheating[:,yClass])
        hotWater.append(stockYear[yClass] * ChotWater[:,yClass])
        electricity.append(stockYear[yClass] * Celectricity[:,yClass])
        cooling.append(stockYear[yClass] * Ccooling[:,yClass])
        # Fixaa muut rakennukset F325 * G14*D67 jne, eli aina vika paikka
        heating[yClass][7] = heatingOther[yClass]
        hotWater[yClass][7] = hotWaterOther[yClass]
        electricity[yClass][7] = electricityOther[yClass]
        cooling[yClass][7] = coolingOther[yClass]
    # SUMs [1x8] inputs for energy.py
    heatingSUM = sum(heating, axis = 0) # 0, D396:D403
    hotWaterSUM = sum(hotWater, axis = 0)# 1, E396:E403
    electricitySUM = sum(electricity, axis = 0) # 2, F396:F403
    coolingSUM = sum(cooling, axis = 0) # 3, G396:G403
    eConsOutput = [heatingSUM, hotWaterSUM, electricitySUM, coolingSUM]
    return eConsOutput


def CalcStockChange(userFloorAreas, userBuildingShares):
    # apulaskenta käyttötavan muutosta varten: M318:AI325
    multp = userFloorAreas * (1-userBuildingShares[:,0])
    # muokkaa matriisimuotoiseksi
    multpM = ones(([nR,nC]))
    for inde in range(nR):
        multpM[inde,:] *= multp[inde]
    sharesByYear = userBuildingShares[:,2:9] # G7:M7
    # 1) pinta-alat rakennusvuosittain M318:S324
    areasByYear = multpM * sharesByYear
    # 2) muutokseen menevät T318:Z324
    changeStock = areasByYear * userBuildingShares[:,21:28]
    # 3) vanhaa jäljellä muutoksen jälkeen AA318:AG324
    # tarvitaan ene-korjauslaskentaan
    remainingOld = areasByYear - changeStock
    # Sums
    changeStockSum1 = sum(changeStock, axis = 0) # AI318:AI324
    changeStockSum2 = sum(changeStock) # AI325
    remainingOldSum = sum(remainingOld, axis = 1) # AH318:AH324
    # Energiakorjauksen jälkeen kannan koko
    # sarakkeet AK...BF
    # AK: areas energy reparing also E318:E325
    repAreas = remainingOldSum * userBuildingShares[:,1]
    # fixaa muut rakennukset
    # vanha muut rakennukset F325
    oldOther = (1-userBuildingShares[7,0])\
                  * (1-userBuildingShares[7,1]) * userBuildingShares[7,1]
    repAreas[7] = userFloorAreas[7]* oldOther
    # vain jos remainingOld<jäljellä => jäljellä - remainingOld, muuten 0
    remaining = []
    stockYear = []
    for cDummy in range(6):
        if cDummy == 0:
            reduct = repAreas
        else:
            reduct = remaining[cDummy-1]
        check = remainingOld[:,cDummy] - reduct
        checkFin = [0 if i > 0 else i for i in check] # set zeros
        remaining.append(checkFin)
    # VUOSILUKUSARAKKEET
    for cDummy2 in range(7):
        if cDummy2 == 0:
            red = repAreas
            check2 = remainingOld[:,cDummy2] - red
            checkFin2 = [0 if i < 0 else i for i in check2] # set zeros
            stockYear.append(checkFin2)
        else:
            check2 = remainingOld[:,cDummy2] - stockYear[cDummy2-1]
            check2Fin = [0 if i < 0 else i for i in check2] # loput ehdot
            stockYear.append(check2Fin)
    # Output
    # 0 = changeStockSum2, [1x1] AI325
    # 1 = repAreas, [1x8] E318:E325
    # 2 = stockYear, [8x7], AZ318:BF324 (+extra row = 0)
    # 3 = oldOther [1x1], F325
    changeOutput = [changeStockSum2, repAreas, stockYear, oldOther] #[remainingOld, changeStock]
    return changeOutput

def CalcEmissions(userBuildingShares, userFoundTypeShares,
                  areaNew, repAreas, newAreas):
    # rows 330-337
    ## 1 = New Stock
    materialSharesAll = userBuildingShares[:,12:15] # Q7:S14, materiaalityypit
    # A materials D330:D337
    matMult = materialSharesAll * matCO2coefs
    # Sum
    matMultSum = sum(matMult, axis = 1) # [1x8] t/brm2
    # B energy efficiency, E330:E337
    enEffNewStock = userBuildingShares[:,9:12]
    enEff = enEffLevel * enEffNewStock
    enEffSum = sum(enEff, axis = 1) # [1x8] [-]
    # C Foundations F330:F337
    found1 = userFoundTypeShares[0,:]
    found2 = userFoundTypeShares[1,:] * demFoundConsts
    foundSum = found1 + found2
    # Final coefficient G330:G337 = A*B*C
    coefFin = matMultSum * enEffSum * foundSum
    # Emissions H330:H337
    newStockEm = coefFin * areaNew # OUTPUT[0]
    newStockEmSum = sum(newStockEm) # OUTPUT[1]
    ## 2 Energy renovation
    # A materials L330:L337
    matSharesEneR = userBuildingShares[:,18:21]
    matEneR = matSharesEneR * matCO2coefs
    matEneRsum = sum(matEneR, axis = 1) # [1x8], [t/brm2]
    # B energy efficiency, M330:M337
    enEffShares = userBuildingShares[:, 15:18]
    enEff2 = enEffShares * enEffLevel
    enEff2Sum = sum(enEff2, axis = 1)
    # Final coefficient N330:N337
    coefFin2 = matEneRsum * enEff2Sum
    # Emissions O330:O337
    enReEm = coefFin2 * repAreas # OUTPUT[2]
    enReEmSum = sum(enReEm) # OUTPUT[3]
    ## 3 Alteration of use
    # A materials S330:S337
    matAltSum = matMultSum * altUseConsts
    # Final coefficient V330:V337
    coefFin3 = altUseConsts2 * matAltSum
    # Emissions
    altEm = coefFin3 * newAreas # OUTPUT[4]
    altEmSum = sum(altEm) # OUTPUT[5]
    # Collate outputs
    emOutput = []
    emOutput.append(newStockEm) # 0, H330:H337, [tCO2e], [1x8]
    emOutput.append(newStockEmSum) #1, H338, [tCO2e], [1x1]
    emOutput.append(enReEm) #2 O330:O337, [tCO2e], [1x8]
    emOutput.append(enReEmSum) #3 O338, [tCO2e], [1x1]
    emOutput.append(altEm) #4, V330:V337 [tCO2e], [1x8]
    emOutput.append(altEmSum) #5 V338, [tCO2e], [1x1]
    return emOutput

def CalcAlterationEneRep(userFloorAreas, userBuildingShares):
    # For alteration of use...rows 207..226
    # Calculate first changes in the stock
    changeStock = CalcStockChange(userFloorAreas, userBuildingShares) # AI325
    sharesAfterChange = userBuildingShares[:,28] # AG7:AG14
    # Then calculate areas of new
    newAreas = changeStock[0] * sharesAfterChange # H318:H325
    # for Energy repair
    #sumErep = CalcStockChange(userFloorAreas, userBuildingShares)
    # areas energy reparing E318:E325
    repAreas = changeStock[1]
    # Get the multipliers in matrix form
    cFinAll = CalcMultipliersForAltAndErep(userBuildingShares)
    cFinAlt = cFinAll[0] # 8 x[20x3]
    cFineRep = cFinAll[1] #
    cRenAlt = cFinAll[2]
    cRenErep = cFinAll[3]
    renAlt = [] # init
    renRep = [] # init
    for hType in range(nBtypes):
        # renewable calculations
        if hType < 2:
            hDummy2 = 3
        if hType == 2:
            hDummy2 = 0
        if hType > 2:
            hDummy2 = 6
        renC = CrenTot[hDummy2:hDummy2+3,0]
        for cType in range(2):
            if cType == 0:
                c1 = cFinAlt[hType]
                c2 = cFineRep[hType]
            altOutputFin.append(c1 * newAreas[hType])
            eRepOutputFin.append(c2 * repAreas[hType])
            if cType == 1:
                c11 = cRenAlt[hType]
                c22 = cRenErep[hType]
        altDum = c11 * newAreas[hType]
        repDum = c22 * newAreas[hType]
        renAlt.append(altDum * renC)
        renRep.append(repDum * renC)
    # output[0] = altOutputFin
    # output[1] = eRepOutputFin
    # output[2] = repAreas
    # output[3] = newAreas
    # output[4] = renAlt= 8 x [1x3], F229:AC229
    # output[5] = renRep= 8 x [1x3], F261:AC261
    return [altOutputFin, eRepOutputFin, repAreas, newAreas,
            renAlt, renRep]
    
def CalcMultipliersForAltAndErep(userBuildingShares):
    # initialize multiplier variables
    cFinAlt = []
    cFinErep = []
    eRepOutput = []
    c2 = 0.5 # for energy reparations
    # Pick shares for all house types
    materialSharesAll = userBuildingShares[:,12:15] # Q7:S14, materiaalityypit 
    # Loop all house types
    cRenAlt = []
    cRenRep = []
    for hType in range(nBtypes):
        # Initialize matrix form multiplier
        defCMalt = ones(([20,3]))
        defCMeRep = ones(([20,3]))
        # pick the right data
        # c1 = {1.0, 0.5} (0.5 for detached and attached buildings)
        # pickC = {H103:J122, E103:G122, K103:M122}, construction constants
        if hType == 0: # detached house
            hDummy = 2
        if hType == 1: # attached house
            hDummy = 1
        if hType == 3: # apartment house
            hDummy = 0
            pickC = CapartmentOtherB[:,0:3]
        if hType >3: # others
            hDummy = hType
            pickC = CapartmentOtherB[:,3:]
        if hType < 2:
            # tähän kohtaan se, että enekorjauksessa kaikille 0.5!
            c1 = 0.5
            pickC = CdetachedAttachedH[4:,:] # 20 x 3
        else:
            c1 = 1.0
        # Make the calculations
        matTriplet = materialSharesAll[hDummy,:] # 1x3, materiaalit Q,R,S
        # defC pitäis viel kertoo joko areaNew:llä tai enekorjauksella
        defC = floorAtoGrossA[hDummy] * c1 # multiplier
        defC2 = floorAtoGrossA[hDummy] * c2
        defCMalt *= defC # multiplier in matrix form (20x3)
        defCMeRep *= defC2
        # Multiply with material shares
        cFinAlt = defCMalt * matTriplet # final multiplier for alterations
        cFinErep = defCMeRep * matTriplet # final multiplief for energy reparations
        # Multiply with construction constants and save
        altOutput.append(cFinAlt * pickC) # 8 x [20x3]
        eRepOutput.append(cFinErep * pickC) # 8 x [20x3]
        # for renewable calculations
        cRenAlt.append(matTriplet* defC)
        cRenRep.append(matTriplet * defC2)
    return [altOutput, eRepOutput, cRenAlt, cRenRep]


def CalcMatElements(areaNew, userBuildingShares, constMatOutput):
    #--- Elements
    #-- New stock : F171:AF194
    #- Detached houses F171:H194, Attached houses I171:K194
    elementsAll = []
    renewableAll = []
    mTypesAll = userBuildingShares[:,12:15] # shares of material types
    for hType in range(2):
        if hType == 0:
            hDummy = 2
            hDummy2 = 3
        if hType == 1:
            hDummy = 1
            hDummy2 = 3
        k0 = areaNew[hDummy] * floorAtoGrossA[hDummy]
        # pick right row from material types (detached or attached)
        mTypesPick = mTypesAll[hDummy,:]
        k_rest = k0 * mTypesPick # [1x3]
        elementsAll.append(CdetachedAttachedH * k_rest) # save
        renC = CrenTot[hDummy2:hDummy2+3,0]
        renewableAll.append(renC* k_rest)
    #- Apartment, business etc. L171:AC194
    # construction materials L171:N174
    for hType2 in range(6):
        if hType2 == 0:
            hDummy = 0
            CaOtherRest = CapartmentOtherB[:,0:3]# pick the apartment buildings constants
        else:
            hDummy = hType2 + 2
            CaOtherRest = CapartmentOtherB[:,3:6]# pick buildings constants for others
        mTypesAotherB = mTypesAll[hDummy,:] # picks building's materials
        constAOtherB = array([constMatOutput[2][hDummy], # R134, U134, K34, N134?
                        constMatOutput[3][hDummy],
                        constMatOutput[0][hDummy],
                        constMatOutput[1][hDummy]])
        # rest for apartment building
        k2 = areaNew[hDummy] * floorAtoGrossA[hDummy]
        k2fin = mTypesAotherB * k2 # [1 x 3]
        # renewable
        if hType2 == 0:
            hDummy2 = 0
        if hType2 >0:
            hDummy2 = 6
        renC = CrenTot[hDummy2:hDummy2+3,0]
        renewableAll.append(renC * k2fin)
        for nFrames in range(3):
            share = mTypesAotherB[nFrames]
            constBuildings = constAOtherB * share # obs if share=0 => output = []
            constMats.append(constBuildings)
            # Rest
            restMats = CaOtherRest[:,nFrames] * k2fin[nFrames]
            Rest.append(restMats)
    elementOutput = [elementsAll, constMats, Rest, renewableAll]
    # output[0] = elementsAll= 2x[24x3], F171:K194, okt & rt
    # output[1] = constMats = 18 x[1x4],L171:AC174, kt->
    # output[2] = Rest = 18 x [1x20], L175:AC194, kt->
    # output[3] = renewableAll = 8 x [1x3], F197:AC197
    return elementOutput

def CalcMatBuildings(userFoundTypeShares, userNfloors,
                     userFloorAreas, userNewShare, areaNew):
    # Calculate first gross area F134:F141
    grossArea = areaNew * floorAtoGrossA # F134:F141
    # Anturan pituus H134:H141
    baseLength = sqrt(grossArea) * 4 / userNfloors
    #-- PAALUTUS (vain vaativat) J134:J141
    piling = baseLength * userFoundTypeShares[1,:] / pilingDistance
    # paalutuksen massa [t] K134:K141
    pilingMass = piling * pilingDepth * pilingMassPerM
    #-- ANTURAT (base/footing)
    crossCut = baseW * baseH
    # average L134:L141
    baseAve = crossCut[0] * 1e-6 * baseLength * userFoundTypeShares[0]
    baseDem = crossCut[1] * 1e-6 * baseLength * userFoundTypeShares[1]
    baseMass = (baseAve + baseDem) * baseTperM3
    # -- KAIVANNOT (barrow bit, average and demanding) P134:Q141
    # -- TÄYTÖT  (backing average and demanding) S134:T134
    areaPerFloor = grossArea / userNfloors # needed for both
    for inde in range(2): # average and demanding
        share = areaPerFloor * userFoundTypeShares[inde]
        c1 = barrowPitC[inde]
        c2 = fillingC[inde]
        pit = share * c1 # barrow pit
        filling = share * c2 # filling
        barrowPit.append(pit)
        fillingAll.append(filling)
    # sums
    barrowPitSum = sum(barrowPit, axis = 0) # R134:R141
    fillingAllSum = sum(fillingAll, axis = 0) # U134:U141
    # collate output
    matOutput = []
    matOutput.append(pilingMass)# [0] K134:K141
    matOutput.append(baseMass) # [1] N134:N141
    matOutput.append(barrowPitSum)# [2] R134:R141
    matOutput.append(fillingAllSum)# [3] U134:U141
    return matOutput

# @ author Maija Mattinen, SYKE, 2015
# -*- coding: utf-8 -*-
#
# Tämä laskentakoodi perustuu KEKO ekolaskuriin. 
# SYKEn internet-sivulla olevan KEKO ekolaskurin osoite on www.ymparisto.fi/keko 
# Tätä viittausta KEKOon ja SYKEen internet-sivun osoitetta ei saa poistaa koodin alusta 
# vaikka koodia muokattaisiin.
# Import needed constants and the numpy package
import numpy
from numpy import *
from KEKOEnergyConstant import *
def CalcEnergy(userEmCoefValues,userFuelShares, BuildingEneUseOld,
               userCOPvalues, userEfficiencies,
               userCoolingShares, BuildingCooling,
               userCHPelectricityProduction,
               userOtherThanCHPshares, BuildingElectricityUse,
               userEmCoeffs, BuildingEneUseNew,
               userCHPheatProduction, userBuildingTime):
    ###### This is the topmost function in the hierarchy that calls other functions ######
    ###### and returns the final outputs for the UI
    # @params: userEmCoefValues = annual change in emission factors [3x1],
    # userFuelShares = fuel shares for house types [11x8], BuildingEneUseOld =,
    # userCOPvalues = , userEfficiencies =,
    # @output:
    # INITIALIZE SOME PARAMETERS
    CumEmElectricity = []#zeros((n_years,n_col)) # initialize output variable for electricity
    # Energy and heating requirement
    heatRequirementAll = [] # ...will be [2x11]
    eneRequirementAll = [] # ...will be [2x9]
    # Heating, electricity and cooling variables
    emHeating = [] # EmissionsHeating, for saving J115, M115, Z115, AC115
    emEle = [] # Emissions electricity, old: K115, N115, new: AA115, AD115
    emCool = [] # Emissions cooling, old: L 115,O115 new: AB115, AE115
    # Outputs C168:C170 and C217:C219
    heatingOutput = []
    electricityOutput = []
    coolingOutput = []
    # At year 50
    heatingEND = []
    electricityEND = []
    coolingEND = []
    # Cumulative result variables
    CumEmElectricityALL = []
    CumEmHeatingALL = []
    CumEmCoolingALL = []
    EmissionsAllCUM = []
    # ele CHP
    eleCHP_all = []
    # Annual results
    emAllYear = []
    ## ----Calculate heat and energy requirement
    #for stockFlag in nStockTypes:
    # this loops types of stock (old and new)
    # old - K71:K81
    heatRequirement = CalcHeatRequirement(userFuelShares, BuildingEneUseOld) # heat requirement
    # new
    heatRequirementNew = CalcHeatRequirement(userFuelShares, BuildingEneUseNew) # heat requirement
    # "real CHP heat consumption" X37 (needed for C113 and S113, update)
    realCHPcons = heatRequirement[0] + heatRequirementNew[0] # K71 + AA71
    # Calculate electricity/heat ratio for CHP X36
    if(userCHPheatProduction > 0):
        eleRatioCHP = userCHPelectricityProduction / userCHPheatProduction # X36
    else:
        eleRatioCHP = 0 
    # for energy pick first the electric network share from user input
    userNetworkShare = userOtherThanCHPshares[0]
    # eneRequirement (old) C131:C139 [MWh/a]
    eneRequirement = CalcEneRequirement(heatRequirement, userEfficiencies,
                userCOPvalues, userCoolingShares,
                BuildingCooling[:,0], userCHPelectricityProduction,
                userNetworkShare, BuildingElectricityUse[:,0],
                BuildingElectricityUse[:,0], 0,
                eleRatioCHP, realCHPcons) # energy requirement old
    eneRequirementNew = CalcEneRequirement(heatRequirementNew, userEfficiencies, userCOPvalues,
        userCoolingShares, BuildingCooling[:,1], userCHPelectricityProduction,
        userNetworkShare, BuildingElectricityUse[:,1],
        BuildingElectricityUse[:,0], 1,
        eleRatioCHP, realCHPcons) # energy requirement new
    eleCHP_old = CalcRegionalCHPeleOutput(BuildingElectricityUse[:,0],
                    userCHPelectricityProduction, BuildingElectricityUse[:,0], 0,
                    eleRatioCHP, realCHPcons)
    eleCHP_new = CalcRegionalCHPeleOutput(BuildingElectricityUse[:,1],
                    userCHPelectricityProduction, BuildingElectricityUse[:,0], 1,
                    eleRatioCHP, realCHPcons)
    # Collate variables
    #Heat requirement 0 = old , 1 = new
    heatRequirementAll.append(heatRequirement)
    heatRequirementAll.append(heatRequirementNew)
    # energy requirement 0 = old , 1 = new
    eneRequirementAll.append(eneRequirement)
    eneRequirementAll.append(eneRequirementNew)
    # eleCHP, 0 = old, 1=new
    eleCHP_all.append(eleCHP_old)
    eleCHP_all.append(eleCHP_new)
    ###----- Start calculating the final outputs
    ##--- 1st FOR
    for bType in range(nStockTypes):
        # clear some variables
        EmElectricityCUM = zeros((n_years,n_col)) # 51 x 2 (c1=average,c2=marginal)
        EmHeatingCUM = zeros((n_years,n_col)) # 51 x 2 (c1=average,c2=marginal)
        EmCoolingCUM = zeros((n_years,n_col)) # 51 x 2 (c1=average,c2=marginal)
        ### 2nd FOR
        for coefFlag in flags:# use average and marginal emission factors
            if coefFlag == "average": # emission factor dummy (for output saving)
                f_dummy = 0 
            if coefFlag == "marginal": # marginal
                f_dummy = 1
            # pick either old or new stock
            heatReq = heatRequirementAll[bType]
            buildingEleUse = BuildingElectricityUse[:,bType]
            eneReq = eneRequirementAll[bType]
            eleCHP = eleCHP_all[bType]
            # For both:
            BuildingEleUseOld = BuildingElectricityUse[:,0]
            # Calculate heating emissions
            # 6.5.2016 updated CalcHeatingEmissions():
            # added one input: eleCHP that is needed for CalcFuelHeat()
            EmissionsHeatingAll = CalcHeatingEmissions(heatReq,
                userEfficiencies, userCOPvalues, userEmCoeffs,coefFlag, eleCHP)
            #  old: J115, M115 new = Z115, AC115, t CO2eq/a
            EmissionsHeatingAllSum = sum(EmissionsHeatingAll) # sum
            emHeating.append(EmissionsHeatingAllSum) # OUTPUT 1: [0]=old,average,[1]=old,marg,[2]=new,ave,[3]=new,marg
            # Calculate electricity emissions
            # old: K115, N115, new: AA115, AD115, t CO2eq/a
            EmissionsEle = CalcElectricityEmissions(buildingEleUse,
                        userCHPelectricityProduction,userNetworkShare, userEmCoeffs,
                        userEfficiencies,coefFlag, BuildingEleUseOld, bType,
                        eleRatioCHP, realCHPcons, heatReq)
            emEle.append(EmissionsEle) # OUTPUT 2: [0]=old,average,[1]=old,marg,[2]=new,ave,[3]=new,marg
            # Calculate cooling related emissions
            # old: L 115,O115 new: AB115, AE115
            EmissionsCool = CalcCoolingEmissions(eneReq, userEmCoeffs, coefFlag)
            #EmissionsCooling[f_dummy] = CalcCoolingEmissions(eneReq, userEmCoeffs, coefFlag)
            emCool.append(EmissionsCool) # OUTPUT 3: [0]=old,average,[1]=old,marg,[2]=new,ave,[3]=new,marg
            ### 3rd FOR: Then loop the given years, i.e.
            # Calculate the cumulative emission results for each year
            for calc_year in calc_years:## 
                if calc_year == calc_years[0]:
                    y_dummy = 0 # initialize year dummy for output saving
                # Cumulative emissions of electricity, sum(sähköverkko,sähköCHP)
                EmEleCUM = RecCalcCumulativeEmissionsElectricity(calc_year,
                            eneReq, userEmCoeffs, userEmCoefValues,
                            coefFlag, bType, userBuildingTime)
                EmElectricityCUM[y_dummy][f_dummy] = EmEleCUM # 51 x 2, row 155&
              # Cumulative emissions of heating, [9x51]
                emHeatingExtra = EmissionsHeatingAll[2:4] # pick the needed extra inputs (J86&J87 / M86&M87)
                EmHeatCUM = RecCalcCumulativeEmissionsHeating(calc_year,
                        eneReq, userEmCoeffs, userEmCoefValues,
                        coefFlag, emHeatingExtra,
                        bType, userBuildingTime)
                EmHeatingCUM[y_dummy][f_dummy] = EmHeatCUM
                # Cumulative emissions of cooling
                EmCoolCUM = RecCalcCumulativeEmissionsCooling(calc_year,
                        eneReq, userEmCoeffs, userEmCoefValues, coefFlag,
                        bType, userBuildingTime)
                EmCoolingCUM[y_dummy][f_dummy] = EmCoolCUM
                y_dummy += 1 # grow the year dummy
        # Save cumulative results for three categories:
        # XXX = {Electricity, Heating, Cooling}
        # CumEmXXXALL[0] = [51x2] for old stock (average&marginal)
        # CumEmXXXALL[1] = [51x2] for new stock (average& marginal)
        CumEmElectricityALL.append(EmElectricityCUM) # 0 = old, 1 = new
        CumEmHeatingALL.append(EmHeatingCUM)
        CumEmCoolingALL.append(EmCoolingCUM)
    # Sum up cumulative results using average and marginal emission factor
    for inde in range(2):
        emAllY = zeros(51)
        # EmAllCUM - dummy of size [1x51]
        EmAllCUM = CumEmElectricityALL[0][:,inde] + \
                              CumEmElectricityALL[1][:,inde] + \
                              CumEmHeatingALL[0][:,inde] + \
                              CumEmHeatingALL[1][:,inde] + \
                              CumEmCoolingALL[0][:,inde] + \
                              CumEmCoolingALL[1][:,inde]
        EmissionsAllCUM.append(EmAllCUM) # save
        # Heating, electricity, cooling outputs
        # old stock + new stock, average/marginal emission factor
        dummy = inde + 2
        heatingSUM = emHeating[inde] + emHeating[dummy]
        electricitySUM = emEle[inde] + emEle[dummy]
        coolingSUM = emCool[inde] + emCool[dummy]
        # save summing results
        heatingOutput.append(heatingSUM)
        electricityOutput.append(electricitySUM)
        coolingOutput.append(coolingSUM)
        # Heating, electricity and cooling at year 50, 
        # BB155,156,157 or BB207,208,209
        heatingEND.append(CumEmHeatingALL[0][50,inde] + \
                CumEmHeatingALL[1][50,inde])
        electricityEND.append(CumEmElectricityALL[0][50,inde] +\
                     CumEmElectricityALL[1][50,inde])
        coolingEND.append(CumEmCoolingALL[0][50,inde] + \
                CumEmCoolingALL[1][50,inde])
        # Calculate annual emissions, row 159 or 211
        for inde2 in calc_years:
            emAllY[inde2] = CalcEmYear(inde2,EmissionsAllCUM, inde)
        emAllYear.append(emAllY) # save emAllYear[0] = average, [1] = marginal
    ## ----Select the outputs to be returned##
    # Emissions for heating, electricity and cooling,
    # each of size [2x1] (average, marginal)
    # Cumulative emissions for heating, electricity,
    # cooling size, each [size n_years x 2]
    # c1 = with average emission coefficient2,
    # c2 = marginal emission coefficients
    # Collate output
    output_fin = []
    output_fin.append(emHeating) # 0 # J115, M115, Z115, AC115
    output_fin.append(emEle) # 1# K115, N115, AA115, AD115
    output_fin.append(emCool) # 2 # L115, O115,AB115,AE115
    output_fin.append(heatingEND) # 3 # BB156, BB208
    output_fin.append(electricityEND) # 4 #BB155, BB207
    output_fin.append(coolingEND) # 5 # BB157, BB209
    output_fin.append(EmissionsAllCUM) # 6 # D158:BB158, D210:BB210
    output_fin.append(emAllYear) # 7 # D159:BB159, DD211:BB211
    output_fin.append(heatingOutput) # 8 # C168, C217
    output_fin.append(electricityOutput) # 9 # C169, C218
    output_fin.append(coolingOutput) # 10 # C170, C219
    return output_fin

##############################################################################
###### The following functions are called by the function "CalcEnergy" #######
##############################################################################
def CalcEmYear(year, emissionsAllCUM, coefType):
    if year == 0:
        return 0
    if year == 1:
        return emissionsAllCUM[coefType][1]
    else:
        previous = emissionsAllCUM[coefType][year-1]
        output = emissionsAllCUM[coefType][year] - previous
        return output

## --- Recursive functions for cumulative calculations-- ###
def RecCalcCumulativeEmissionsElectricity(year, eneRequirement,userEmCoeffs, userCoefValues,
                                          coefFlag, bType, userBuildingTime):
    # This function calculates the cumulative emissions related to
    # electricity
    # for a given year
    # and with the given emission factor set (average or marginal)
    # excel: D131: BB131
    userBuildingTimeF = userBuildingTime * 1.0
    if year == 0: # For year 0 no cumulative emissions
        return 0
    if bType == 1 and year < (userBuildingTimeF/2):
        return 0
    # Prepare somethings before cumulative calculations..
    # Get emissions from all 9 sources
    EmissionsYearAll = CalcYearEmissions(year, eneRequirement, userEmCoeffs,
                        userCoefValues, coefFlag)

    # Pick only emissions related to electricity (electric network and electricity CHP)
    emissions_electricity = EmissionsYearAll[0:2]
    sumElectricity = sum(emissions_electricity) # Then sum these two elements related to electricity
    # Then start calculations
    if year == 1:
        # Return the sum of these two elements related to electricity
        return sumElectricity
    if year >= 1:
        # Get the previous year's emissions with recursion
        EmPreviousYear = RecCalcCumulativeEmissionsElectricity(year-1,
                        eneRequirement, userEmCoeffs, userCoefValues,
                        coefFlag, bType, userBuildingTime)
        output = sumElectricity + EmPreviousYear # Sum up and return output
        return output

def CalcYearEmissions(year, eneRequirement,
                        userEmCoeffs, userCoefValues, coefFlag):
    # This function calculates the emissions from all 9 sources
    # for a given year
    # with the given emission factor set
    # @input:
    # @output:
    coefs_fin = zeros(9) # initialize coefficient variable [9x1]
    # Get the needed emission factor set for the calculation
    coefs = CalcEmissionFactor(year-1, userEmCoeffs, userCoefValues, coefFlag)
    # For convenience, rearrange emissions factors [8x1] -> [9x1]
    coefs_fin[0] = coefs[0]
    coefs_fin[1:3] = coefs[1]
    coefs_fin[3:10] = coefs[2:8]
    # Calculate emissions from all 9 sources
    EmissionsAll = eneRequirement * coefs_fin * 1e-3
    return EmissionsAll # return output size = [9x1]

def RecCalcCumulativeEmissionsHeating(year, eneRequirement,userEmCoeffs,
                        userCoefValues, coefFlag, emHeating,
                        bType, userBuildingTime):
    # This function calculates the cumulative emissions related to heating
    # for a given year
    # and with the given emission factor set (average or marginal)
    # excel: 
    # ------
    userBuildingTimeF = userBuildingTime * 1.0
    if year == 0:  # For the year 0 no cumulative emissions
        return 0
    if bType == 1 and year < (userBuildingTimeF/2): # uuden kannan päästöt lähtee rakennusajan puolestavälistä
        return 0
    # Get the emissions for all 9 sources for the cumulative calculation
    EmAll = CalcYearEmissions(year, eneRequirement, userEmCoeffs,
                              userCoefValues, coefFlag)
    heating = EmAll[2:7]
    sum_heating = sum(heating) # sum the heating emissions
    heating_all = sum_heating + sum(emHeating) # sum heating and emissions from bio fuels and fire places
    # Then start calculations
    if year == 1:
        return heating_all
    if year >= 1:
        EmPreviousYear = RecCalcCumulativeEmissionsHeating(year-1,
                        eneRequirement, userEmCoeffs,
                        userCoefValues, coefFlag, emHeating,
                        bType, userBuildingTime)
        output = heating_all + EmPreviousYear
        return output

def RecCalcCumulativeEmissionsCooling(year, eneRequirement,userEmCoeffs,
                        userCoefValues, coefFlag, bType, userBuildingTime):
    # This function calculates the cumulative emissions related to
    # xxx  for a given year
    # and with the given emission factor set (average or marginal)
    # excel: 
    # ------
    userBuildingTimeF = userBuildingTime * 1.0
    if year == 0:  # For the year 0 no cumulative emissions
        return 0
    if bType == 1 and year < (userBuildingTimeF/2): # uuden kannan päästöt lähtee rakennusajan puolestavälistä
        return 0
    # Get the emissions for all 9 sources for the cumulative calculation
    EmAll = CalcYearEmissions(year, eneRequirement, userEmCoeffs, userCoefValues, coefFlag)
    cooling = EmAll[7:9]
    sum_cooling = sum(cooling) # sum the cooling emissions
    # Then start calculations
    if year == 1:
        return sum_cooling
    if year >= 1:
        # Get the emissions of previous year
        EmPreviousYear = RecCalcCumulativeEmissionsCooling(year-1,eneRequirement,
                        userEmCoeffs, userCoefValues, coefFlag,
                        bType, userBuildingTime)
        output = sum_cooling + EmPreviousYear    # Sum and return output
        return output
################

def CalcHeatRequirement(fuelShares, heatConsumptionBuildings):
    # This function calculates the energy requirement for all (8) different building types
    # In Excel Energia laskenta cells C61:J71 can be replicated with this function
    # @ params: fuelShares = the shares of different fuels (11) used in the buildings (8)
    # Size fuelShares = [11 x 8], eneConsumptionBuildings = output of building calculation,
    # includes the energy consumption (heating & hot water in kWh) of each housetype
    # sife heatConsumptionBuildings = [8 x 2]
    #####
    # First sum the energy consumptions (heating+hot water)
    heatTotal = heatConsumptionBuildings.cumsum(axis=1)[:,1]
    # Then multiply with the shares
    heatRequirementsBuildings = fuelShares * heatTotal *1e-3 # size = [11 x 8]
    # Return only the sums of each row, desired output size = [11x1]
    heatRequirements = heatRequirementsBuildings.cumsum(axis=1)[:,7]
    return heatRequirements

def CalcEneRequirement(heatRequirement, userEfficiencies, userCOPvalues,
                       coolingShares, coolingBuilding,userCHPelectricityProduction,
                       userNetworkShare, BuildingElectricityUse,
                       BuildingEleUseOld, bType, eleRatioCHP,
                       realCHPcons):
    # this function calculates the energy requirement in MWh/a for 9 categories:
    # electric network, electricity CHP, district heating CHP,
    # district heating separate production, house-specific oil, house specific gas,
    # heating electricity, cooling, cooling electricity
    # Replicates the calculation of laskenta ENERGIANTUOTANTO C121:C129
##Parametrit uudelle: CalcEneRequirement(heatRequirementNew, userEfficiencies, userCOPvalues,
##        userCoolingShares, BuildingCooling[:,1], userCHPelectricityProduction,
##        userNetworkShare, BuildingElectricityUse[:,1],
##        BuildingElectricityUse[:,0], 1,
##        eleRatioCHP, realCHPcons)
    ##--C132 = D113 for convenience calc this first
    # C113 was updated 17.7.2015 according to VTT input
    eleCHP = CalcRegionalCHPeleOutput(BuildingElectricityUse,
                    userCHPelectricityProduction, BuildingEleUseOld, bType,
                    eleRatioCHP, realCHPcons) # C113
    # D113 was updated 9.5.2016 according to Aalto input
    # 23.8.2016 Added zero checks
    aid1 = eleCHP/0.39 # C113/0.39
    aid2 = heatRequirement[0]/0.9 # C94/0.9
    aid_check = aid1 + aid2
    if aid_check > 0:
        electricityCHP = ((heatRequirement[0] + eleCHP) / userEfficiencies[0])*(aid1/(aid1+aid2))
    else:
        electricityCHP = 0
    electricityNetwork = CalcElectricityOther2(BuildingElectricityUse,
                            userCHPelectricityProduction,userNetworkShare,
                            eleCHP, bType, eleRatioCHP, realCHPcons) # FIXXX
    electricityNetworkFin = electricityNetwork * 1e3
    ##--- C123:C126 = D84,D85,D88,D89. Make use of the function "CalcFuelHeat"
    fuelEnergyAll = CalcFuelHeat(heatRequirement, userEfficiencies, eleCHP) # [6x1]
    # pick only cells D84,D85,D88,D89 from array including "all" D84:D89
    fuelSelection = array([0,1,4,5])
    fuelEnergy = fuelEnergyAll[fuelSelection] # size=[4x1] ## 2-5
    ##--- C127 = sum(G90:G93) make use of the output of CalcElectricityHeat function
    electricityHeating = CalcElectricityHeat(heatRequirement, userCOPvalues) 
    result_electricityHeating = sum(electricityHeating) # sum cells # 6
    ##--- C128= C101 = K76 = sum(C76:J76)
    # First pick the right cooling input (other cooling= 2nd column (index=1))
    coolingSharesOther = coolingShares[:,1]
    coolingOther = coolingSharesOther * coolingBuilding *1e-3
    result_coolingOther = sum(coolingOther) # [1x1] - OK ## 7
    ## ---C129 = H100 = K75/COP4
    # First calculate K75 (cooling with heat pumps)
    # pick the heat pump cooling:
    coolingSharesHP = coolingShares[:,0]
    coolingHP = coolingSharesHP * coolingBuilding *1e-3
    sum_coolingHP = sum(coolingHP)
    # divide with the COP value of heat pumps
    result_coolingHP = sum_coolingHP / userCOPvalues[3] # [1x1] - OK ## 8
    ## Collate the final output of the function
    n_output = 9
    eneRequirements = zeros(n_output) # init output variable [9x1], MWh/a
    # here fixed 17.9.15 electricityNetwork -> electricityNetworkFin
    eneRequirements[0:2] = [electricityNetworkFin, electricityCHP] # indices 0-1
    eneRequirements[2:6] = fuelEnergy # indices 2-5
    eneRequirements[6:9] = [result_electricityHeating,
                            result_coolingOther, result_coolingHP] # indices 6-8
    return eneRequirements

def CalcRegionalCHPeleOutput(BuildingElectricityUse,
                    userCHPelectricityProduction,
                    BuildingEleUseOld, bType,
                    eleRatioCHP, realCHPcons):
    # This function was updated 17.7.2015
    # updated cells: C113, S113, S114, added calculation in X36:X38
    buildingElectricityReq0 = sum(BuildingEleUseOld)*1e-3 # C112
    buildingElectricityReq = sum(BuildingElectricityUse)*1e-3
    # update: replace X30 * 1000 by X38
    # X36 = eleRatioCHP, X37 = AA71 + K71 = realCHPcons
    # X38 = X36 * X37
    X38 = eleRatioCHP * realCHPcons
    CHPelectricityOutput = X38
    if CHPelectricityOutput > buildingElectricityReq0:
        CHPelectricity0 = buildingElectricityReq0
    else:
        CHPelectricity0 = CHPelectricityOutput
    if bType == 0:
        CHPelectricity = CHPelectricity0
    if bType == 1:
        if CHPelectricityOutput > CHPelectricity0:
            CHPelectricity = CHPelectricityOutput - CHPelectricity0
        else:
            CHPelectricity = 0
    return CHPelectricity # CHP sähköntuotanto alueella

def CalcElectricityOther2(BuildingElectricityUse, userCHPelectricityProduction,
                         userNetworkShare, regionalCHPeleP, bType,
                        eleRatioCHP, realCHPcons):
    # This function calculates the other electricity
    ## in excel, old C131 = I106 = D51 * C114 = D51 * [sum(F8:F15)*1e-3 - X20*1e3]
    ## new Y106 = D51 * S114 = ...
    buildingElectricityReq = sum(BuildingElectricityUse)*1e-3 # C112
    #CHPelectricityOutput = userCHPelectricityProduction*1e3 # CHP electricity production
    X38 = eleRatioCHP * realCHPcons
    CHPelectricityOutput = X38
    if bType == 0:
        if CHPelectricityOutput > buildingElectricityReq:
            otherThanCHP = 0
        else:
            # FIX 27.11.2017:
            otherThanCHP = userNetworkShare * (buildingElectricityReq-CHPelectricityOutput)
        electricity_result = otherThanCHP
    if bType == 1:
        otherThanCHP = userNetworkShare * (buildingElectricityReq - regionalCHPeleP) * 1e-3
    electricity_result = otherThanCHP
    return electricity_result # returns output, size = [1x1]


def CalcElectricityEmissions(BuildingElectricityUse, userCHPelectricityProduction,
                             userNetworkShare, userEmCoeffs, userEfficiencies, coefFlag,
                             BuildingEleUseOld, bType, eleRatioCHP, realCHPcons, heatRequirement):
    # This function returns the emissions related to electricity according
    # emissions are calculated using either average or marginal emission coefficients
    # K96 & K103 = Average, N96& N103 = Marginal
    # First pick either average or marginal emission coefficient for calculations
    if coefFlag == "average":
        Emcoef1 = userEmCoeffs[9]
        Emcoef2 = userEmCoeffs[0]
    else: # i.e. marginal
        Emcoef1 = userEmCoeffs[10]
        Emcoef2 = userEmCoeffs[1]
    # tässä valitaan joko CHP laitoksen sähkön tuotanto tai todellinen sähkön tarve
    # Ja lasketaan muu kuin CHP sähköntuotanto
    # electric network ...eg.K106 = I106 * E106 * 1e-3
    CHPelectricityP = CalcRegionalCHPeleOutput(BuildingElectricityUse,
                    userCHPelectricityProduction, BuildingEleUseOld,
                    bType, eleRatioCHP, realCHPcons)
    electricNetwork = CalcElectricityOther2(BuildingElectricityUse,
                        userCHPelectricityProduction,
                         userNetworkShare, CHPelectricityP, bType,
                        eleRatioCHP, realCHPcons )# I106
    emissionNetwork = electricNetwork * Emcoef1 # K106, N106 or AA106, AD106
    aid1 = CHPelectricityP/0.39 # C113/0.39
    aid2 = heatRequirement[0]/0.9 # C94/0.9
    aid_check = aid1+aid2
    if userEfficiencies[0] >0:
        part1 = ((heatRequirement[0] + CHPelectricityP) / userEfficiencies[0])
    else:
        part1 = 0
    if aid_check >0:
        electricityCHP = part1 *(aid1/(aid1+aid2))
    else:
        electricityCHP = 0
    if(userEfficiencies[0] > 0):
        emissionCHPele = Emcoef2 * electricityCHP * 1e-3 # updated 10.5.2016
    else:
        emissionCHPele = 0
    # Sum emissions of network and electricity from CHP
    electricityEmissions = emissionNetwork + emissionCHPele # K113
    debug = electricNetwork
    return electricityEmissions

def CalcHeatingEmissions(heatRequirement, userEfficiencies,userCOPvalues,
                         userEmCoeffs,CoefFlag, eleCHP):
    # laskenta ENERGIA J84:J93 (average) or M84:M93 (marginal -- OK
    # @params heatRequirement, from CalcHeatRequirement [11x1],
    # userEfficiencies (etas) [6x1], userCOPvalues (COP values) [4x1]
    #  userEmCoeffs[11x1] (emission coefficients), CoefFlag ("average"/"marginal")
    # Collate the needed emission coefficients based on the selection (average/marginal)
    if CoefFlag == "average": 
        coefSelection = array([0,2,4,5,6,7,9])
    else:
        coefSelection = array([1,3,4,5,6,7,10])
    emCoeffs = userEmCoeffs[coefSelection]
    # this point eleCHP is needed
    fuelHeat = CalcFuelHeat(heatRequirement, userEfficiencies, eleCHP)
    electricityHeat = CalcElectricityHeat(heatRequirement, userCOPvalues)
    result_fuel = fuelHeat * emCoeffs[0:6] * 1e-3 
    result_electricity = electricityHeat * emCoeffs[6] * 1e-3
    #collate output
    resultHeatEmissions = zeros(10)
    resultHeatEmissions[0:6] = result_fuel
    resultHeatEmissions[6:11] = result_electricity
    return resultHeatEmissions # size = [10x1]

def CalcCoolingEmissions(eneRequirement, userEmCoeffs, coefFlag):
    # Calculates the emissions from cooling either using
    # average or marginal emission coefficients
    # L100 + L101 -OK
    if coefFlag == "average":
        coefHP = userEmCoeffs[9]
        coefOther = userEmCoeffs[8]
    else: # i.e. pick the marginal coefficients
        coefHP = userEmCoeffs[10]
        coefOther = userEmCoeffs[8]
    # Then calculate the emissions for heat pumps
    # in excel: L100 = H100 * E96 * 1e-3 = C129*Q42*1e-3, C129 = eneRequirement[8]
    emission_coolingHeatPumps = eneRequirement[8] * coefHP * 1e-3
    # And for other type of cooling
    # in excel L101 = E101*C101*1e-3 = K76*Q38*1e-3=
    emission_coolingOther = eneRequirement[7] * coefOther * 1e-3
    # Obtain the output by summing heat pump and other cooling emissions
    emissionsCooling = emission_coolingHeatPumps + emission_coolingOther
    return emissionsCooling


##############################################################################
### Here are the auxiliary functions called from calculation functions  ######
##############################################################################

def CalcFuelHeat(heatRequirement, userEfficiencies, eleCHP):
    # This function calculates the
    # @params
    # @output fuelEnergy = Fuel-based heat [MWh] 
    ##Laskenta Energia cells D84:D89, size=[6x1]
    # in newer excel cells D94:D99...
    # pick cells "K61:K66" from heatRequirement
    setHeatRequirement1 = heatRequirement[0:6]
    # Divide the heat demands with the respective efficiencies (eta) (K_i/eta_i)
    # here must be userEfficiencies > 0
    fuelEnergy = setHeatRequirement1 / userEfficiencies
    # Updated here 9.5.2016, district heating CHP share calculation, i.e. fuelEnergy[0]
    # according to Aalto input
    # 23.8.2016 added zero checks
    dummy1 = heatRequirement[0]/0.9
    dummy2 = eleCHP/0.39
    dummy_check = dummy1 + dummy2
    if userEfficiencies[0] > 0:
        pala1 = ((heatRequirement[0] + eleCHP)/userEfficiencies[0])
    else:
        pala1 = 0
    if dummy_check > 0:
        fuelEnergy[0] = pala1*(dummy1/(dummy1+dummy2))
    else:
        fuelEnergy[0] = 0
    return fuelEnergy # return output size = [6x1]

def CalcElectricityHeat(heatRequirement, userCOPvalues):
    # This function calculates the
    # @params:
    # @output:
    ##--- Calculates and returns cells G90:G93 [4x1]
    #pick cells "K67,K68,K69" from heatRequirement
    selection2 = array([6,7,8])
    setHeatRequirement2 = heatRequirement[selection2]
    # pick COP1...COP3
    setCOP = userCOPvalues[0:3]
    # calculate K_i/COP_i
    # HERE must be setCOP > 0
    electricityHeating = setHeatRequirement2 / setCOP # G90:G92
    # Collate cells in an array
    result_electricityHeating = zeros(4)
    result_electricityHeating[0:3] = electricityHeating
    result_electricityHeating[3] = heatRequirement[9]
    return result_electricityHeating # returns [4x1] 

def CalcEmissionFactor(year, userEmCoeffs, userCoefChangeValues,coefFlag):
    # This function calculates the emission factor for a given year (average/marginal)
    # @input: year= the year the factor is calculated, userEmCoeffs=user input of coefficients
    # userCoefChangeValues = user input of annual change in emission factor,
    # coefFlag = selection of average/marginal set
    # @output= set of emission factors, size [8x1]
    # The output variables rows represent the following:
    # electric network electricity, district heating:CHP,
    # district heating:separate thermal production, house-specific:oil,
    # house-specific:gas, electricity for heating, cooling, electricity for cooling
    # -----
    # Form the factors at t=0 [8x1] according to user input
    averageIndices = array([9,0,2,6,7,9,8,9]) # average indices in desired order
    marginalIndices = array([10,1,3,6,7,10,8,10]) # marginal indices in desired order
    Factors0Average = userEmCoeffs[averageIndices] # form average set
    Factors0Marginal = userEmCoeffs[marginalIndices] # form marginial set
    # For the calculation, form the [8x1] coefficients from [3 x 1] user input
    dummy1 = userCoefChangeValues[0] # 
    dummy2 = userCoefChangeValues[1] #
    dummy3 = userCoefChangeValues[2] #
    CoefValues = array([dummy1,dummy2,dummy2,dummy3,dummy3,dummy1,0,dummy1]) # form coef set
    # Then select either average or marginal factors
    if coefFlag == "average":
        Factors0 = Factors0Average
        cooling = Factors0Average[6]
    else: # i.e. marginal
        Factors0 = Factors0Marginal
        cooling = Factors0Marginal[6]
    # Calculate the emission factor for the desired year
    emFactors = Factors0 * power(CoefValues, year)
    # Fix the factor for cooling that remains constant
    emFactors[6] = cooling
    return emFactors # returns set of emission factors size = [8x1] 
# @ author Maija Mattinen, SYKE, 2015
# -*- coding: utf-8 -*-
#
# Tämä laskentakoodi perustuu KEKO ekolaskuriin. 
# SYKEn internet-sivulla olevan KEKO ekolaskurin osoite on www.ymparisto.fi/keko 
# Tätä viittausta KEKOon ja SYKEen internet-sivun osoitetta ei saa poistaa koodin alusta 
# vaikka koodia muokattaisiin.
# Import constants and numpy package
import numpy
from numpy import *
from KEKOInfraConstant import *
# OBS
# before this calculation can be executed,
# KEKO_building.py has to be executed and some results
# provided for CalcInfra - function! (buildingsInput)

def CalcInfra(userBuildingTime, userRoadLengths, userRoadWidths,
            userRoadFoundTypes, userRailwayLengths,
            userParkingNorm, userFloorArea,
            userAverageParkArea, userParkingShares,
            userGreenArea, userNetVolume, buildingsInput):
    ###### This is the topmost function in the hierarchy that calls other functions ######
    ###### and returns the final outputs
    # initialize output variable
    infraOutput = []
    # Calculate materials for roads
    areaRoads = CalcAreaRoad(userRoadLengths,userRoadWidths) # road areas
    # Tie- ja ratarakentamisen päästöt
    resultInfraEmissions = CalcInfraConstEm(userRoadLengths, areaRoads,
                        userRailwayLengths) # 0
    # Pysäköinti
    resultParking = CalcParking(userParkingNorm, userFloorArea,
                userAverageParkArea, userParkingShares) # 1
    # Tierakentamisen materiaalit
    resultRoad = CalcRoadMaterials(userRoadFoundTypes, areaRoads) #2
    # Ratarakentamisen materiaalit Calculate materials for railways 
    resultRailway = CalcRailWayMaterials(userRailwayLengths,
                                   C_Mat_RailConst) # 3
    resultMatSum = CalcMatSum(resultRailway[2], resultRoad[6],
                              resultParking[2]) # 4 
    # Calculate the green space related results 
    resultGreenSpace = CalcGreenSpace(userGreenArea) # 5
    # Results related to underground cavities
    resultUnderground = CalcUndergroundCavity(userNetVolume) # 6
    # Results for the technical networks
    # OBS NEEDS inputs from KEKO_buildings.py
    resultNetworks = CalcNetworks(buildingsInput) # 7
    # Cumulative emission results
    resultCum = CalcEmCumResults(userBuildingTime,
                resultInfraEmissions, resultParking,
                resultGreenSpace, resultUnderground,
                resultNetworks[0], resultNetworks[1]) # 8
    # Materials total results
    resultMatTot = CalcMatSumResult(resultMatSum, resultUnderground[0],
                        resultNetworks[2]) # 9
    ## Collate output ##
    infraOutput.append(resultInfraEmissions)
    infraOutput.append(resultParking)
    infraOutput.append(resultRoad)
    infraOutput.append(resultRailway)
    infraOutput.append(resultMatSum)
    infraOutput.append(resultGreenSpace)
    infraOutput.append(resultUnderground)
    infraOutput.append(resultNetworks)
    infraOutput.append(resultCum)
    infraOutput.append(resultMatTot)
    return infraOutput

#############################################################################
###### The following functions are called by the function "CalcInfra" #######
#############################################################################
def CalcMatSumResult(tNetwork, underground, networks):
    # summing the materials:
    # liikenneverkko + louhitut tilat + tekniset verkot
    output = tNetwork + underground + sum(networks)
    # output = [1x1], [t] , D250
    return output

def CalcEmCumResults(userBuildingTime, resultInfraEmissions, outputParking,
                   resultGreenSpace, resultUnderground, networkConst,
                     networkMaint):
    # Infra rakentaminen, päästöt per annum ja cumulative
    # Infra maintenance cumulative emissions
    # Infra total, cumulative
    # Infra materials
    # Arrange needed inputs
    if userBuildingTime == 0:
        empty = zeros(nCalcYears)
        output = [empty, empty, empty,
                  empty, empty]
        return output
    else:
        constructionRoad = resultInfraEmissions[0]
        constructionParking = outputParking[0]
        maintenanceRoad = resultInfraEmissions[1]
        maintenanceParking = outputParking[1]
        greenAreaBefore = resultGreenSpace[1]
        greenMaint = resultGreenSpace[2]
        undergroundBefore = resultUnderground[1]
        undergroundMaint = resultUnderground[2]
    ## First: construction emissions
        transportNetwork_extra = zeros(nCalcYears) # init
        sumInfra = sum(constructionRoad) + constructionParking # sum road+parking emissions
        transportNetwork_extra[0:userBuildingTime] = sumInfra / userBuildingTime # only for construction years
    # Viheralueet
        greenArea_extra = zeros(nCalcYears) # init
        greenArea_extra[0:userBuildingTime] = greenAreaBefore / userBuildingTime
    # Louhitut tilat
        underground_extra = zeros(nCalcYears) # init
        underground_extra[0:userBuildingTime] = undergroundBefore / userBuildingTime
    # Tekniset verkot
        networks_extra = zeros(nCalcYears) # init
        networkConst_sum = sum(networkConst)
        networks_extra[0:userBuildingTime] = networkConst_sum / userBuildingTime
    ## Sum construction emissions per annum
        constEmTot = transportNetwork_extra + greenArea_extra + \
                 underground_extra + networks_extra
        constEmTot_cum = cumsum(constEmTot) # Cumulative
    ## Second:Maintenance related emissions
    # liikenneverkko
        tnetworkMaint_extra = zeros(nCalcYears) # init
        maintenanceRoad_sum = sum(maintenanceRoad, axis = 0)
        tnetwork_before = maintenanceRoad_sum[0] + maintenanceParking[0]
        tnetwork_after = maintenanceRoad_sum[1] + maintenanceParking[1]
    # take only "after"
        deltaTnetwork = tnetwork_after #- tnetwork_before
        tnetworkMaint_extra[0:userBuildingTime] = deltaTnetwork / userBuildingTime
    # green space
        greenMaint_extra = zeros(nCalcYears) # init
        deltaGreenMaint = greenMaint[1] #- greenMaint[0]
        greenMaint_extra[0:userBuildingTime] = deltaGreenMaint / userBuildingTime
    # underground
        undergroundMaint_extra = zeros(nCalcYears) # init
        deltaUnderMaint = undergroundMaint[1] #- undergroundMaint[0]
        undergroundMaint_extra[0:userBuildingTime] = deltaUnderMaint / userBuildingTime
    # networks - korjattu 1.10.2015
        networkMaint_extra = zeros(nCalcYears) # init
        networkMaint_sum = sum(networkMaint)
        deltaNetworkMaint = 0
        deltaNetworkMaint = networkMaint_sum
        networkMaint_extra[0:userBuildingTime] = networkMaint_sum / userBuildingTime
    # maintenance emissions per annum
        maintEmTot = tnetworkMaint_extra + greenMaint_extra + \
                 undergroundMaint_extra + networkMaint_extra
        maintEmTot_cum = cumsum(maintEmTot) # cumulative
        maintEmTot_cum_cum = cumsum(maintEmTot_cum) # 2. cumulative
    # Total cumulative
        tot_cum = constEmTot_cum + maintEmTot_cum_cum
    # Collate output
    # output[0] = constEmTot, [1x50] [t CO2eqv/a], E213:BB213
    # output[1] = constEmTot_cum,[1x50] [tCO2eqv/a], E219:BB219
    # output[2] = maintEmTot_cum,[1x50] [tCO2eqv/a], E228:BB228
    # output[3] = maintEmTot_cum_cum,[1x50] [tCO2eqv/a], E227:BB227
    # output[4] = tot_cum, [tCO2eqv],[1x50] E237:BB237
        cumResults = [constEmTot, constEmTot_cum, maintEmTot_cum,
                  maintEmTot_cum_cum, tot_cum]
        output =  cumResults
        return output

def CalcNetworks(buildingsInput):
    # Calculates the emissions and materials related to technical networks
    # Emissions calculation with the aid of coefficients,
    # first construction phase, then the use phase
    EmissionsConstruction = buildingsInput[0] * TechnicalNetworkCoefficients
    EmissionsUse = NetworkUseEmissionCoefficient * EmissionsConstruction
    # Materials calculation with the aid of coefficients
    # first construction phase, then the use phase
    MaterialsConstruction = buildingsInput[1] * TechnicalNetworkCoefficients
    network_output = [EmissionsConstruction, EmissionsUse,
                      MaterialsConstruction] # collate the output
    # network_output[0] = EmissionsConstruction[1x3] [tCO2eqv],
    # sähkö- ja tietoliikenneverkot; kaukolämpöverkot; vesihuoltoverkot
    # network_output[1] = EmissionsUse [1x3] [tCO2eqv]
    # network_output[2] = MaterialsConstruction [1x2] [t]
    return network_output


def CalcUndergroundCavity(userNetVolume):
    # Calculates the emissions and amount of rock related to excavation 
    # i.e. underground cavity or similar
    GrossVolume = userNetVolume * MinableVolumeConversion
    deltaRock = GrossVolume[1] - GrossVolume[0]
    if deltaRock < 0:#make sure that delta > 0, otherwise 0
        deltaRock = 0 
    amountRock = DensityRock * deltaRock
    excavationEmission = deltaRock * ExcavationConstructionEmissions
    lifecycleEm = GrossVolume * ExcavationOtherEmissions / 100
    undergroundOutput = [amountRock, excavationEmission, lifecycleEm]
    # UndergroundOutput[0] = amountRock [1x1] [t], F158
    # UndergroundOutput[1] = excavationEmission, [1x1] tCO2eqv, D161 
    # UndergroundOutput[2] = lifecycleEm, [1x2], [t CO2eqv/a], D163:E163
    return undergroundOutput

def CalcGreenSpace(userGreenArea):
    # Calculates green space results
    deltaGreen = userGreenArea[1] - userGreenArea[0] # new area
    if deltaGreen > 0:
        emissionsGreenConstr = deltaGreen * infraMatConsts[2,0] / 1000
    else:
        emissionsGreenConstr = 0
    # Maintenance
    maintenanceGreen = userGreenArea * infraMatConsts[2,1] / 1000 
    # greenOutput[0] = deltaGreen [1x1]
    # greenOutput[1] = emissionsGreenConstr [1x1]
    # greenOutput[2] = maintenanceGreen [1x2], [t/a]
    greenOutput = [deltaGreen, emissionsGreenConstr, maintenanceGreen]
    return greenOutput

def CalcMatSum(MatRailwaySum, RoadMatSum, builtParkingArea_sum):
    # D133:D136, output = D139
    parkingMat = MatRoadBuilding[0:4,0] * builtParkingArea_sum
    parkingMat_sum = sum(parkingMat)
    output = sum(MatRailwaySum) + RoadMatSum + parkingMat_sum
    # output = [t] D139
    return output

def CalcRailWayMaterials(userRailwayLengths,C_Mat_RailConst):
    # Calculates the materials needed for railways
    # Two types of railways single- and double-track
    # D122:E130 = delta* constants
    delta = userRailwayLengths[1,:] - userRailwayLengths[0,:] # new railway length
    matRailway1 = delta[0] * C_Mat_RailConst #0 single-track,  D122:D130
    matRailway2 = delta[1] * 2 * C_Mat_RailConst #1 double-track, E122:E130
    # Sum
    matRailway1_sum = sum(matRailway1)
    matRailway2_sum = sum(matRailway2)
    sums = [matRailway1_sum, matRailway2_sum]
    # Collate the output
    # output[0] = [1x8], päällyrakenne, maarakennus, alusrakenne, ratajohto
    # sillat, tunnelit, muut rakenteet, ratapihat
    # output[1] = [1x8]
    # output[2] = sums [1x2]
    output =[matRailway1, matRailway2, sums] 
    return output

def CalcRoadMaterials(userRoadFoundTypes, areaRoads):
    ## NOLLAKORJAUS TÄNNE D113:AD116
    # Calculates the materials for roads
    # areaRoads = [2x9] includes the areas of nine different road types, before (r1) and after (r2) 
    # userRoadFoundTypes = [9x3], includes the shares of foundation types (poor, average, good)
    # C_Mat_RoadConst = [24x3], includes the constants (see constant-file)
    # Calculates for each road type (9 road types) materials (3 types)
    materialsRoad = zeros([nRoadTypes,nRoadMatTypes,nFoundTypes]) # initialize
    # Calculate delta in roadAreas
    areaRoads_delta = areaRoads[1] - areaRoads[0] 
    areaRoads_delta [areaRoads_delta < 0] = 0 # if delta<0 => 0, NOLLAKORJAUS
    for index in range(nRoadTypes): # loop the 6 different road types
        if index < 4:
            dum = 0
        else:
            dum = index - 3
        road_dummy1 = dum * nRoadMatTypes
        road_dummy2 = (dum + 1) * nRoadMatTypes
        materialsRoad[index,:,:] = \
            MatRoadBuilding[road_dummy1:road_dummy2,:] *\
            userRoadFoundTypes[index,:] * areaRoads_delta[index] # D113:AD116
    # Sum needed outputs
    materialsRoad_sum1 = sum(materialsRoad, axis = 0) #1 [4x3] AE113:AG116
    materialsRoad_sum1_sum1 = sum(materialsRoad_sum1,axis = 0) #2 [1x3] AE117:AG117
    materialsRoad_sum2 = sum(materialsRoad, axis = 1)#3 [9x3] D117:AD117
    materialsRoad_sum2_sum = sum(materialsRoad_sum2, axis = 1)#4 [1x9], row118 values
    materialsRoad_sum1_sum2 = sum(materialsRoad_sum1,axis = 1) # 5 [1x4], AH113:AH116
    tot_sum = sum(materialsRoad_sum1_sum2) # [1x1], AH117
    # Collate output, all [t]
    # output[0] = materialsRoad[9x4x3]=roadtypes x materialtypes x foundconditions D113:AD116
    # output[1] = sum materials, [4x3], r= asfalttibetoni, murske, sora, hiekka; c= good, average,poor
    # output[2] =  sum (good,average,poor), [1x3]
    # output[3] = [9x3]for each road type (r),sum(good,average,poor) (c) 
    # output[4] = sum materials [1x9], [t], row118 values, asuntokatu, kokoojakatu,
    # pääkatu, raskaspääkatu, yhdystie, seututie, valtatie, mottoritie, erill. pyörätie
    # output[5] = sum(road types) [1x4]
    # output[6] = total sum [1x1]
    output = [materialsRoad, materialsRoad_sum1,
                   materialsRoad_sum1_sum1, materialsRoad_sum2,
                   materialsRoad_sum2_sum, materialsRoad_sum1_sum2, tot_sum] 
    return output

def CalcParking(userParkingNorm, userFloorArea,
                userAverageParkArea, userParkingShares):
    # parking D102:F102
    parkingLots = zeros([2,2]) # initialize
    for status in range(2):
        # T15:U18, make sure that zero is not a divisor
        if userParkingNorm[status] == 0:
            nLots = 0
        else:
            nLots = userFloorArea[status]/userParkingNorm[status]
        Pshares = array([userParkingShares[status,0], userParkingShares[status,1]])
        parkingLots[status,:] = nLots * Pshares # n lots before and after
    deltaParking = parkingLots[1,:] - parkingLots[0,:] # new lots "change"
    deltaParking[deltaParking < 0] = 0 #make sure that delta > 0 V15:V16
    # Areas to be built
    builtParkingArea = deltaParking * userAverageParkArea # new area
    parkingAreas = parkingLots * userAverageParkArea # areas before, after
    parkingAreas_sum = sum(parkingAreas, axis = 1) # sum(Y15:Y16) and SUM(Z15:Z16)
    builtParkingArea_sum = sum(builtParkingArea) # sum(X15:X16)
    # Calculate emissions
    ParkingConstruction = builtParkingArea_sum * infraMatConsts[0,0] / 1000 # construction
    ParkingMaintenance = infraMatConsts[1,1] * parkingAreas_sum / 1000 # maintenance
    # parkingOutput[0] = construction
    # parkingOutput[1] = maintenance
    # parkingOutput[2] = builtParkingArea_sum [1x1], needed for material calculation
    parkingOutput = [ParkingConstruction, ParkingMaintenance, builtParkingArea_sum] # Collate output
    return parkingOutput

def CalcInfraConstEm(userRoadLengths, areaRoads, userRailwayLengths):
    # Päästöt rakentaminen: D90:D100
    # Hoito (ennen ja jälkeen) = E90:F100
    # initialize some parameters
    ConstrOutput = [] 
    inputs = zeros(([2,11])) # r1=before, r2=after
    coefsMaintenanceM = ones((11,2)) # needed coefficients in matrix form
    dummy = 4
    coefsConstr = zeros(11)
    # Form "input" lengths/areas
    for status in range(nStatus):
        inputs[status,:] = array([areaRoads[status][0], areaRoads[status][1],
                    areaRoads[status][2],areaRoads[status][3],
                    userRoadLengths[status,4],userRoadLengths[status,5],
                    userRoadLengths[status,6], userRoadLengths[status,7],
                    areaRoads[status][8], userRailwayLengths[status,0],
                  userRailwayLengths[status,1]])
    deltas = inputs[1,:] - inputs[0,:]
    deltas[deltas < 0] = 0 # if deltas <0 => 0 ## fix zeros
    # Form coefficients
    # For construction and maintenance 
    coefsConstr[0:4] = infraMatConsts[0,0]
    coefsConstr[8] = infraMatConsts[1,0]
    coefsConstr[9] = infraCO2consts[5,0]
    coefsConstr[10]= infraCO2consts[4,0]
    coef2_rev = infraCO2consts[0:4,0]
    coef2 = coef2_rev[::-1] # reverse
    # Maintenance
    coefsMaintenanceM[0:4,:] *= infraMatConsts[0,1]
    c2_rev = infraCO2consts[0:4,1]
    c2 = c2_rev[::-1]
    for inde in range(dummy):
        coefsMaintenanceM[inde+dummy,:] *= c2[inde] # indices 4..7
        coefsConstr[inde+dummy] = coef2[inde]
    coefsMaintenanceM[8,:] *= infraMatConsts[1,1]
    coefsMaintenanceM[9,:] *= infraCO2consts[5,1]
    coefsMaintenanceM[10,:] *= infraCO2consts[4,1]
    # Calculate construction
    construction = deltas * coefsConstr / 1000
    # Calculate maintenance
    maintenance = transpose(inputs) * coefsMaintenanceM / 1000 # E90:F100
    output = [construction, maintenance]
    # output[0] = construction [1x11], output[1] = maintenance[11x2]
    return output #
    

def CalcAreaRoad(length_road, width_road):
    # Auxiliary function for area calculation
    # Excel before = O7:O15, after = Q7:Q15
    area_road0 = length_road[0,:] * width_road[1,:] # before
    area_road1 = length_road[1,:] * width_road[1,:] # after
    # Correct areas, where default width is needed 
    defaultIndices = where(width_road[1,:] == 0)[0]
    defaultWid = width_road[0,defaultIndices] 
    area_road0[defaultIndices] = length_road[0,defaultIndices] * defaultWid
    area_road1[defaultIndices] = length_road[1,defaultIndices] * defaultWid
    # Form output
    areaRoads = []
    areaRoads.append(area_road0)
    areaRoads.append(area_road1)
    return areaRoads # [2 x 9], areaRoads[0] = before, areaRoads[1] = after

# @ author Maija Mattinen, SYKE, 2015
# -*- coding: utf-8 -*-
#
# Tämä laskentakoodi perustuu KEKO ekolaskuriin. 
# SYKEn internet-sivulla olevan KEKO ekolaskurin osoite on www.ymparisto.fi/keko 
# Tätä viittausta KEKOon ja SYKEen internet-sivun osoitetta ei saa poistaa koodin alusta 
# vaikka koodia muokattaisiin.
# Import needed constants and the numpy package
import numpy
from numpy import *
from KEKONatureConstant import *

def CalcNature(userNatureAreas, userLargeAreas,
               userValuableAreas, userBuiltAreas,
               userFloorAreas, userBuildingTime,
               userPopWorkplaces):
    ###### This is the topmost function in the hierarchy that calls other functions ######
    ###### and returns the final outputs for the UI
    # Area outputs:
    area_outputs = CalcLandUseSums(userBuiltAreas) # 0
    # NPP, BDI and permeability + indices
    floorAreaTot = CalcFloorAreaTot(userFloorAreas) # needed for other functions
    areaDensity = CalcAreaDensity(userBuiltAreas, userFloorAreas) # area density, needed for calculations
    # Indices
    comp_output = CalcCompValues(userBuiltAreas,floorAreaTot, userNatureAreas,
                areaDensity) # 1
    valuableAreas_output = CalcValuableNatureAreas(userValuableAreas, floorAreaTot) # 2
    largeAreas_output = CalcLargeNatureAreas(userNatureAreas, userLargeAreas, floorAreaTot) # 3
    # Emissions
    em_output = CalcEmissions(userBuildingTime, userBuiltAreas,
                userNatureAreas, userPopWorkplaces, userFloorAreas) # 4
    ## ----Select the outputs to be returned##
    # @output are the following:
    natureOutput = []
    natureOutput.append(area_outputs)# 0
    natureOutput.append(comp_output) # 1
    natureOutput.append(valuableAreas_output) # 2
    natureOutput.append(largeAreas_output) # 3
    natureOutput.append(em_output) # 4
    output = natureOutput
    return output

##############################################################################
###### The following functions are called by the function "CalcNature" #######
##############################################################################


def CalcEmissions(userBuildingTime, userBuiltAreas, userNatureAreas,
                  userPopWorkplaces, userFloorAreas):
    # 1. osa = Biomassan poistuminen, t/v
    # 2. osa = Kumu päästöt
    # 3. osa = Hiilensidonnan väheneminen, t/v
    # 4. osa = Kumu päästöt hiilensidonnasta t
    # Haetaan hiilitulokset
    carbon_output = CalcCarbon(userBuiltAreas, userNatureAreas)
    # 1: tässä vähennys vain rakennusvuosille
    if(userBuildingTime > 0):
        biomass_red_em = carbon_output[0] / userBuildingTime
    else:
        biomass_red_em = 0
    biomass_em_all = zeros(n_calcYears+1) # initialize output
    # Aseta päästövähennys vain rakennusvuosille
    biomass_em_all[1:userBuildingTime+1] = biomass_red_em # row 137
    # 2. osa. Kumu päästöt, biomass_em_all:sta # row 139
    biomass_em_all_cum = cumsum(biomass_em_all)
    # 3. osa. Hiilensidonta
    factors = ones(n_calcYears+1) # initialize
    if(userBuildingTime > 0 ):
        step = 1.0 / userBuildingTime
    else:
        step = 0
    fBuilding = arange(0, 1, step)
    factors[0:userBuildingTime] = fBuilding# muuta rakennusvuosien tiedot
    Csequestration = carbon_output[1] * factors # 51 x1, years 0, 1,...
    Csequestration_cum = cumsum(Csequestration)  # 51 x1, years 0, 1,...
    # Calculate outputs and collate
    em_per_year = biomass_em_all[1:] + Csequestration[1:] # Emissions per year OUTPUT
    em_cum = biomass_em_all_cum[1:] + Csequestration_cum[1:] # Cumulative emissions OUTPUT 
    # Calculate emission characteristics (emissions/pop, emissions/floor area)
    ## Per pop&work places
    popWorkplaces_sum = sum(userPopWorkplaces, axis = 0)
    if(userBuildingTime > 0):
        delta_popWorkplaces = (popWorkplaces_sum[1] - popWorkplaces_sum[0]) \
                          / userBuildingTime# after-before
    else:
        delta_popWorkplaces = 0
    pop_year = ones(51) * popWorkplaces_sum[1] # initialize
    # asetetaan kasvu rakennusvuosille
    pop_year[0] = popWorkplaces_sum[0]
    pop_year[1:userBuildingTime+1] = delta_popWorkplaces
    pop_year_cum = cumsum(pop_year[0:userBuildingTime+1])
    pop_year[0:userBuildingTime+1] = pop_year_cum # now pop_year [51x1]
    ## HERE must be that pop_year[1:] > 0
    em_per_year_pop = em_per_year / pop_year[1:] * 1000 # OUTPUT
    ## Per floor area
    floorArea_sum = sum(userFloorAreas, axis = 1)
    floorArea_year = ones(51) * floorArea_sum[1] # initialize
    if(userBuildingTime > 0):
        delta_floorArea = (floorArea_sum[1]-floorArea_sum[0])/ \
                      userBuildingTime # after-before
    else:
        delta_floorArea = 0
    # aseta kasvu rakennusvuosille
    floorArea_year[0] = floorArea_sum[0]
    floorArea_year[1:userBuildingTime+1] = delta_floorArea
    floorArea_year[0:userBuildingTime+1] = \
                cumsum(floorArea_year[0:userBuildingTime+1])
    em_per_year_floorArea = em_per_year / floorArea_year[1:] * 1000 # OUTPUT
    # Collate outputs
    # em_per_year, [1x50], row 158 [tCO2/a]
    # em_cum, [1x50], row 160, [tCO2]
    # em_per_year_pop, [1x50], row 161, [kg/capita/a]
    # em_per_year_floorArea, [1x50], row 163, [kg/kem2/a]
    em_output = [em_per_year, em_cum, em_per_year_pop,
                 em_per_year_floorArea]
    return em_output # em_per_year_floorArea

def CalcCompValues(userBuiltAreas, kem_tot, userRecAreas, areaDensity):
    # N92:N94
    # Calculates net primary prodaction (NPP), biodiversity index (BDI),
    # and the permeability of the ground
    # suunnitelma
    # #Biomassan nettoprimaarituotanto
    # L92 = J84*1000/J23
    # Because recreation areas have their own calculation
    # pick correct indices
    pick_indices = [0,1,2,3,5,6,7,8,9] # exclude recreation areas
    # 30.4.2015 poistettu myös vesialueet
    area_pick = userBuiltAreas[:,pick_indices]
    builtAreaTot = sum(userBuiltAreas, axis = 1)
    pois = userBuiltAreas[0:2,9]
    builtAreaTot_fin = builtAreaTot - pois
    # NPP outputs
    NPP_outputs = CalcNPP(area_pick, userRecAreas,builtAreaTot_fin)
    delta_NPP = NPP_outputs[1]
    # BDI outputs
    BDI_outputs = CalcBDI(area_pick, userRecAreas, builtAreaTot_fin,
                    areaDensity)
    delta_BDI = BDI_outputs[1]
    # Permeability outputs
    perm_outputs = CalcPerm(area_pick, userRecAreas, builtAreaTot_fin,
                    BDI_outputs[4])
    delta_perm = perm_outputs[1]
    # Collate the three values (NPP, BDI, permeability)
    suunnitelma = zeros(3)
    if(kem_tot > 0):
        suunnitelma[0] = delta_NPP * 1000 / kem_tot # OUTPUT,
        suunnitelma[1] = delta_BDI * 10000/ kem_tot
        suunnitelma[2] = delta_perm * 10000/ kem_tot
    ind_p = suunnitelma/KS_comp_values
    ind_values = ind_p * 100 # *100 %
    # @output: 
    # ind_values [1x3], NPP, BDI, permeability
    output = [ind_values, NPP_outputs, BDI_outputs,
              perm_outputs, suunnitelma]
##  ind_values = [1x3]
##  NPP_outputs = [sum_NPPs, delta_NPP, delta_rel, NPP_ave] = [1x2], [1x1], [1x1], [1x2]
##  BDI_outputs = [sum_BDIs, delta_BDI, delta_rel, BDI_ave, permFactors] = [1x2], [1x1], [1x1], [1x2], array([1x2],[3x2])
##  Perm_outputs= [sum_perms, delta_perm, delta_rel, perm_ave]=[1x2], [1x1], [1x1], [1x2]
##  suunnitelma = [NPP, BDI, perm]=[1x3]
    return output

def CalcCarbon(userBuiltArea, userNatureArea):
    # calculates emissions and carbon sinks
    # BA65 = SUM(BA56:BA64) emissions
    # BC65 = SUM(BC56:BC64) sinks
    # Changes in areas
    delta_builtArea = userBuiltArea[0,:] - userBuiltArea[1,:] # before-after
    delta_natureArea = userNatureArea[0,:] - userNatureArea[1,:] # before-after
    # First calculate carbon in biomass (trees) (AW58:AW64)
    CinTrees = amountTree * biomassExpansionFactor * CshareInBiomass
    # BA 56:57, CO2 emissions of agriculture areas & built parks etc.
    Ccoeff = zeros(7)
    Ccoeff[0] = CinLand[0] * CtoCO2 * LandCshare
    part1 = CinTrees * BiomassCshare
    part2 = CinLand[1:] * LandCshare
    Ccoeff[1:] = (part1 + part2) * CtoCO2
    # check if delta <0 =>0 otherwise multiply with coeffs
    if(delta_builtArea[8]<0):
        em_agr = 0
    else:
        em_agr = delta_builtArea[8] * Ccoeff[0]
    # Dealt with em_rest
    delta_coefFin = [0 if i < 0 else i for i in delta_natureArea[0:6]]
    em_rest = delta_coefFin * Ccoeff[1:]
    em_sum = em_agr + sum(em_rest)
    # Calculate carbon sinks (BC65)
    # if delta <0 => sink = 0
    delta_coefFin2 = [0 if j < 0 else j for j in delta_natureArea[0:5]]
    delta_coefFin2a = array(delta_coefFin2) # convert to an array
    sinks = delta_coefFin2a * CsinkFactor * CtoCO2
    # sum sinks
    sinks_sum = sum(sinks)
    return [em_sum, sinks_sum] # em_sum [t CO2], BA65; sink_sum [t/v] BC65

def CalcLandUseSums(userAreaInput):
    # Sums the land uses
    sums = []
    # C41: buildings
    building_pick = array([0,1,2,3,5])
    sums.append(sum(userAreaInput[1,building_pick]))
    # C42: Transport areas
    sums.append(userAreaInput[1,6])
    # C43: Erityisalueet
    sums.append(userAreaInput[1,7])
    # C44: green and other
    green_pick = array([4,8])
    sums.append(sum(userAreaInput[1,green_pick]))
    # output = sums [1x4], [ha]
    # rakennusten alueet
    # liikennealueet
    # erityisalueet
    # viher- ja muut vapaa-alueet
    return sums

def CalcValuableNatureAreas(valuableAreas, Area_kem_tot):
    # Arvokkaat luontoalueet
    # N102:N105, indeksi %
    delta_areas = valuableAreas[0,:]-valuableAreas[1,:]
    delta_areas_sum = sum(delta_areas)
    X_ala = delta_areas * X_values # K102:K104
    if(Area_kem_tot > 0):
        per_kem = X_ala * 10000 / Area_kem_tot # L102:L104
    else:
        per_kem = 0
    sum_per_kem = sum(per_kem) # yhteensä, summa
    sum_KS = sum(KS_values) # yhteensä, summa
    if(sum_KS > 0):
        IND_p = sum_per_kem / sum_KS # Palauttaa yht-rivin desimaalilukuna
    else:
        IND_p = 0
    IND_points = IND_p * 100 # *100 %
    # Collate output
    valuable_output = [IND_p, IND_points, delta_areas_sum]
    # IND_p & IND_points = [1x1], N105, desimaalilukuna ja prosenttilukuna
    # delta_areas_sum = [1x1] [ha], I105 
    return valuable_output

def CalcLargeNatureAreas(areas, largeAreas, Area_kem_tot):
    # Laajat luontoalueet ja viheralueiden yhteydet
    # Excel: rows 110:119
    # change m2/kem2
    delta_areas = areas[1,:]-areas[0,:]
    Areas = zeros(4)
    Areas[0] = -1 * sum(delta_areas[1:7])
    Areas[1:4] = largeAreas[0:3]
    if (Area_kem_tot >0):
        delta = Areas * 10000 / Area_kem_tot # muutos m2/kem2, laskenta LUONTO I114:I117
    else:
        delta = 0
    # Muutos / KS
    delta2 = delta / KS_consts # K114:K117
    IND = delta2 * 100
    IND_output = average(IND)
    return IND_output # [1x1] N96

##############################################################################
### Here are the functions called from calculation functions  ######
##############################################################################
def CalcPermFactors(areaDensity):
    # Based on area densities, calculates the permeability
    # factors before and after construction
    # In excel: laskenta_LUONTO AD54:AE57
    ## NOLLAKORJAUS
    # tsekkaa onko molemmat log termit ok.. Eli 
    res_consts = perm_consts[0,:] # Pick the right constant values
    other_consts = perm_consts[1,:]
    # Logaritmeihin tarvitaan 4 ekaa aluetyyppiä, poimitaan aluetehokkuudet
    res_density = areaDensity[:,0:2] # kerrostalot, pientalot, K12:L13
    other_density = areaDensity[:,2:4] # keskustatoiminnot, työpaikka-alueet, K14:L15
    # Jos aluetehokkuus = 0 => ln-termi = 0.
    res_logs = log(res_density*100) # Calculate ln(), residential
    #res_logs_fin = [0 if i == -inf else i for i in res_logs]
    other_logs = log(other_density*100) # Calculate ln(), other
    # fix inf-values (if density = 0..)
    other_logs_fin = zeros(([2,2]))
    res_logs_fin = zeros(([2,2]))
    perm_res = zeros(([2,2]))
    perm_other = zeros(([2,2]))
    for inde in range(2):
        # set zeros if necessary
        for inde2 in range(2):
            if isinf(res_logs[inde][inde2]) == True:
                res_logs_fin[inde][inde2] = 0
                perm_res[inde][inde2] = 1
            else:
                res_logs_fin[inde][inde2] = res_logs[inde][inde2]
                perm_res[inde][inde2] = 1-(res_consts[0]*\
                            res_logs_fin[inde][inde2]+res_consts[1])/100
            if isinf(other_logs[inde][inde2]) == True:
                other_logs_fin[inde][inde2] = 0
                perm_other[inde][inde2] = 1
            else:
                other_logs_fin[inde][inde2] = other_logs[inde][inde2]
                perm_other[inde][inde2] = 1-(other_consts[0]*\
                        other_logs_fin[inde][inde2]+other_consts[1])/100
    permFactors = zeros([4,2]) # Collate factors
    permFactors[0:2,:] = transpose(perm_res)
    permFactors[2:4,:] = transpose(perm_other)
    return permFactors # 4x2, c0 = before, c1= after

def CalcFloorAreaTot(userFloorAreas):
    # Lasketaan kokonais kem
    sum_floorArea = sum(userFloorAreas, axis=1) # sum areas before and after, respectively
    floorAreaTot = sum_floorArea[1]-sum_floorArea[0] # delta, tot
    return floorAreaTot # J23

def CalcAreaDensity(userBuiltAreas, userFloorAreas):
    # Aluetehokkuuden laskeminen
    # c0 = before c2 = after constructions
    # K12:L20
    pickBuiltAreas = userBuiltAreas[0:8] # excluding vesialueet
    pickFloorAreas = userFloorAreas[0:8] # excluding vesialueet
    nonzeroFloor = where(pickFloorAreas >0)  # don't divide by 0
    areaDensity = zeros([2,9]) # initialize output
    areaDensity[nonzeroFloor] = pickFloorAreas[nonzeroFloor]/\
                    (pickBuiltAreas[nonzeroFloor] * 10000)
    return areaDensity # K12:L20


def CalcNPP(area_pick, userRecAreas, BuiltAreaTot):
    # Calculates NPP outputs
    ####---- NPP
    NPPs = NPP_constants * area_pick # 0=before 1 = after
    # omit vesialueet (index 8)
    NPPs_fin = NPPs[0:2,0:8]
    # Recreation area NPP G58:I58 = I81:K81
    NPP_recArea = NPPs_recreationArea * userRecAreas
    sum_NPP_recArea = sum(NPP_recArea, axis=1)
    # Sum and add recreation area NPP
    sum_NPPs = sum(NPPs_fin, axis=1) + sum_NPP_recArea # G65, H65 OUTPUT
    delta_NPP = sum_NPPs[1] - sum_NPPs[0] # I65, OUTPUT
    # Calculate some charasteristics related to change
    if(sum_NPPs[0] > 0):
        delta_rel = delta_NPP / sum_NPPs[0]
    else:
        delta_rel = 0
    if (BuiltAreaTot[0] > 0 and BuiltAreaTot[1] > 0):
        NPP_ave = sum_NPPs / BuiltAreaTot
    else:
        NPP_ave = [0.,0.]
    NPP_output = [sum_NPPs, delta_NPP, delta_rel, NPP_ave]
    return NPP_output

def CalcBDI(area_pick, userRecAreas, BuiltAreaTot, areaDensity):
    # Calculates BDI outputs
    ####---- Maankäytön biodiversiteetti-indeksi (BDI)
    # T65-S65 = SUM(T54:T63)-SUM(S54:S63)
    BDIs = BDI_constants * area_pick
    # Fix the 4 first values with permeability
    # First get the permeability factors (AD54:AE57)
    permFactors = CalcPermFactors(areaDensity) # muotoa 4x2
    fixed1  = BDIs[:,0:4] * transpose(permFactors) # 2x4
    BDIs[:,0:4] = fixed1 # fix values
    # omit vesialueet (index 8)
    BDIs_fin = BDIs[0:2,0:8]
    # Recreation areas U81 and V81
    BDI_recArea = BDIs_recreationArea * userRecAreas
    sum_BDI_recArea = sum(BDI_recArea, axis=1)
    ## Sum and add recreation area BDI
    sum_BDIs = sum(BDIs_fin, axis = 1) + sum_BDI_recArea # S65 and T65 OUTPUT
    delta_BDI = sum_BDIs[1] - sum_BDIs[0] # Delta (after-before), U65 OUTPUT
    # Calculate some characteristics related to change
    if(sum_BDIs[0] > 0):
        delta_rel = delta_BDI / sum_BDIs[0]
    else:
        delta_rel = 0
    if (BuiltAreaTot[0] > 0 and BuiltAreaTot[1] > 0):
        BDI_ave = sum_BDIs / BuiltAreaTot
    else:
        BDI_ave = [0.,0.]
    BDI_output = [sum_BDIs, delta_BDI, delta_rel, BDI_ave, permFactors]
    return BDI_output

def CalcPerm(area_pick, userRecAreas, BuiltAreaTot, permFactors):
    #####---- Permeability
    # AF54:AG64
    # Form permeability coefficients for aa area types
    perm_coefs = zeros(([9,2])) # initialize
    perm_coefs[0:4,:] = permFactors # residential and other
    perm_coefs[4:9,0] = perm_rest_c # rest from constants
    perm_coefs[4:9,1] = perm_rest_c
    perms = transpose(perm_coefs) * area_pick
    # omit vesialueet (index 8)
    perms_fin = perms[0:2,0:8]
    # recreation area AH81 and AI81
    perm_recArea = perm_consts_recArea * userRecAreas
    sum_perm_recArea = sum(perm_recArea, axis=1)
    # Sum and add recreation area permeability
    sum_perms = sum(perms_fin, axis=1) + sum_perm_recArea # AF65 and AG65 OUTPUT
    delta_perm = sum_perms[1] - sum_perms[0] # AH65 OUTPUT
    # Calculate some characteristics related to change
    if(sum_perms[0] > 0):
        delta_rel = delta_perm / sum_perms[0]
    else:
        delta_rel = 0
    if (BuiltAreaTot[0] > 0 and BuiltAreaTot[1] > 0):
        perm_ave = sum_perms / BuiltAreaTot
    else:
        perm_ave = [0.,0.]
    perm_output = [sum_perms, delta_perm, delta_rel, perm_ave]
    return perm_output
# @ author Maija Mattinen, SYKE, 2015
# -*- coding: utf-8 -*-
#
# Tämä laskentakoodi perustuu KEKO ekolaskuriin. 
# SYKEn internet-sivulla olevan KEKO ekolaskurin osoite on www.ymparisto.fi/keko 
# Tätä viittausta KEKOon ja SYKEen internet-sivun osoitetta ei saa poistaa koodin alusta 
# vaikka koodia muokattaisiin.
# Import needed constants and the numpy package
import numpy
from numpy import *
from KEKOTransportConstant import *

def CalcTransport(userCityType, userPopShareCenter, userPopShareDens,
                  userPopShareZones, userPopShareDist,
                  userPopulation, userFloorArea, userBuildingTime):
    ###### This is the topmost function in the hierarchy that calls other functions ######
    ###### and returns the final outputs for the UI
    # Initialize output variable
    output = []
    emissionsY = []
    # Calculate and save outputs for conditions "before" and "after"
    for tIndex in nToLoop:
        passengerKms = CalcPassengerKm(userCityType, userPopShareCenter,
                    userPopShareDens, userPopShareZones, userPopShareDist,
                    tIndex)
        output.append(passengerKms) # before = output[0], after = output[4]
        # Calculate kilometers per annum
        passengerKmsY = passengerKms[0] * 365
        output.append(passengerKmsY) # before = output[1], after = output[5]
        # Calculate transport distribution
        if(passengerKms[1] > 0):
            transportDistribution = passengerKms[0] / passengerKms[1]
        else: transportDistribution = 0
        output.append(transportDistribution) # before = output[2], after = output[6]
        # Calculate Emissions and Energy consumption
        EmissionsEnergyOutput = CalcEmissionsEnergy(passengerKmsY, userPopulation,
                                userFloorArea, tIndex)
        output.append(EmissionsEnergyOutput)# before = output[3], after = output[7]
        # Take all emissions, except walking and cycling.
        emY_all = EmissionsEnergyOutput[0] # emissions per annum, all
        emY_sum_woWb = sum(emY_all[0:5]) # sum all excep walking and cycling
        emissionsY.append(emY_sum_woWb) # save
    # Calculate cumulative emissions
    cumEmissions = CalcCumEmissions(emissionsY, userBuildingTime,
                    userPopulation)
    output.append(cumEmissions) # output[8]
    ## ----Select the outputs to be returned##
    return output

##############################################################################
###### The following functions are called #######
##############################################################################
def CalcCumEmissions(emSum, userBuildingTime, userPopulation):
    # Calculates emissions per capita, total,and cumulative
    # with new technology
    delta = emSum[1] - emSum[0] # after - before
    if(userBuildingTime > 0):
        extra = delta / userBuildingTime
    else:
        extra = 0
    em_all = zeros(n_calcYears + 1) # init
    em_all[0] = emSum[0] # Year 0 = "before"
    em_all[1:userBuildingTime+1] = extra # lisäys rakennusvuosille
    em_all_cum = cumsum(em_all) # row 261
    # Population growth
    delta_pop = userPopulation[1] - userPopulation[0]
    if(userBuildingTime > 0):
        extra_pop = delta_pop / userBuildingTime
    else:
        extra_pop = 0
    pop_all = zeros(n_calcYears +1) # initialize
    pop_all[0] = userPopulation[0]
    pop_all[1:userBuildingTime+1] = extra_pop
    pop_all_cum = cumsum(pop_all) # row 260
    # Calculate emissions [t CO2eqv/a] taking account the techn. eff.
    em_all_fin = em_all_cum * techEffFactors # CO2 kg/capita/a new technology, row 262
    em_all_pop = em_all_fin * pop_all_cum / 1000# Whole population [CO2 t/a], row 263
    em_all_pop_cum = cumsum(em_all_pop[1:]) # cumulative emission [t CO2], row 264
    # Collate output
    cumEmOutput = [em_all_fin[1:], em_all_pop[1:], em_all_pop_cum]
    return cumEmOutput

def CalcEmissionsEnergy(passengerKmsY, userPop, userFloorArea, tIndex):
    # Calculates CO2-eqv emissions and energy consumption
    # per habitant and per floor area
    # F226:F232, G226:G232, H226:H232, I226:I232
    # First re-arrange passenger kilometers
    # tIndex picks either values "before"(0) or "after" (1)
    kms = zeros(8)
    kms[0] = passengerKmsY[2]
    kms[1] = passengerKmsY[3]
    kms[2] = passengerKmsY[4]
    kms[3] = passengerKmsY[6]
    kms[4] = passengerKmsY[5]
    kms[5] = passengerKmsY[0]
    kms[6] = passengerKmsY[1]
    # Then calculate emissions
    emissions = kms[0:7] * CO2energyPerHkm[:,0]/1000 # kg CO2eqv/capita/a
    if(userFloorArea[tIndex] >0):
        emissions_kem = emissions * userPop[tIndex] / userFloorArea[tIndex] # kg CO2eqv/kem
    else:
        emissions_kem = 0
    # Calculate Energy consumption
    energy = kms[0:7] * CO2energyPerHkm[:,1] # kWh/capita/a
    if(userFloorArea[tIndex] >0):
        energy_kem = energy * userPop[tIndex] / userFloorArea[tIndex] # kWh/kem
    else:
        energy_kem = 0
    # Collate output
    output = [emissions, emissions_kem, energy, energy_kem] 
    return output

def CalcPassengerKm(userCityType, userPopShareCenter, userPopShareDens,
                    userPopShareZones, userPopShareDist, tIndex):
    # Lasketaan henkilökilometrit yhteensä
    # Yhteenveto: J191:J199 = kerroin * keskiarvo
    factors = CalcFactors(userCityType, userPopShareCenter, tIndex)
    average = CalcTripAverage(userPopShareDens, userPopShareZones,
            userPopShareDist, tIndex)
    # Calculate Passenger kilometers
    passengerKms = factors * average
    # Re-arrange output, and sum cars and split buses
    passengerKmsFin = passengerKms
    passengerKmsFin[2] = sum(passengerKms[2:4]) # sum cars
    passengerKmsFin[3] = passengerKms[4] * shareDieselBus 
    passengerKmsFin[4] = passengerKms[4] * shareGasBus
    passengerKmsFin_sum = sum(passengerKmsFin)
    output = [passengerKmsFin, passengerKmsFin_sum]#factors
    return output

def CalcFactors(userCityType, userPopShareCenter, tIndex):
    # Lasketaan rivi 174 "kerroin" = row 172 / row 173 =
    # kilometrit / kansallinen keskiarvo
    # Haetaan valinnan mukaan kilometrit (r=kaupunkiseutu, c=kulkumuoto)
    kilometers = tripsInCities[userCityType,0:8]
    # Add car kilometers (as driver and as passenger)
    # G162:H162
    carKmsForCity = carKmInZones[userCityType,:] # all 4 values
    part1 = userPopShareCenter[tIndex,:] * carKmsForCity
    part1_driver = part1 * shareAsDriver
    part1_passenger = part1 * shareAsPassenger
    kilometers[2] = sum(part1_driver)
    kilometers[3] = sum(part1_passenger)
    factors = kilometers / factorAveFin
    return  factors # [8x1], E174:L174

   
def CalcTripAverage(userPopShareDens, userPopShareZones, userPopShareDist,
                    tIndex):
    # Lasketaan yhdyskuntarakenteellisten valintojen
    # matkasuoritteiden kerkiarvo, row 182
    # SUM(E179:E181)/COUNT(E179:E181) ...
    # Muokkaa kerroin matriisimuotoiseksi 
    kerroin1 = userPopShareDens[tIndex] # starting point, user input
    kerroin1M = ones(([nAreaTypes, nTransportModes])) # initialize matrix form
    for inde in range(nAreaTypes): # set shares in matrix
        kerroin1M[inde,:] *= kerroin1[inde]
    trips1 = kerroin1M * tripsByAreaDens[0:5, 0:8]
    trips1_sum = sum(trips1, axis = 0)
    # Eri yhdyskuntarakenteen vyöhykkeillä (liikkumisvyöhykkeillä) asuvien matkat
    kerroin2 = userPopShareZones[tIndex] # starting point
    kerroin2M = ones(([nZones, nTransportModes])) # initialize
    for inde2 in range(nZones): # set shares in matrix
        kerroin2M[inde2,:] *= kerroin2[inde2]
    trips2 = kerroin2M * tripsInZones[0:7, 0:8]
    # fix rows 124 ja 125
    trips2[1, :] = kerroin2M[2,:] * tripsInZones[1,0:8]
    trips2[2, :] = kerroin2M[1,:] * tripsInZones[2,0:8]
    trips2_sum = sum(trips2, axis = 0)
    # Supermarkettiin. Vähintään 1000 myynti-m2
    # päivittäistavarakauppojen saavutettavuusvyöhykkeillä asuvien matkat
    # E138:L138
    kerroin3 = userPopShareDist[tIndex] # starting point, user input
    kerroin3M = ones(([nDistGroups, nTransportModes])) # initialize
    for inde3 in range(nDistGroups): # set shares in matrix
        kerroin3M[inde3,:] *= kerroin3[inde3]
    trips3 = kerroin3M * tripsSupermarket[0:3, 0:8]
    trips3_sum = sum(trips3, axis = 0)
    # Calculate average of the trips
    trips_all = []
    trips_all.append(trips1_sum)
    trips_all.append(trips2_sum)
    trips_all.append(trips3_sum)
    trips_ave = average(trips_all, axis=0)
    output = trips_ave # ORIG
    return output 
 
