def detTotalWeightChange(inputArr, spikeTrain, iterations, showPlot):
    # Initialize the time steps required to emulate the total runtime iteratively
    dt = 1  # Time between iterations
    train = spikeTrain
    totalDuration = train.shape[1]  # Total duration to run
    timeToEnumerate = np.arange(
        1, totalDuration + 1,
        1)  # Determine the time-step array [0, 0.125, 0.25, 0.375, ..., 800]
    # Assign initial parameters
    # ---------------------------------
    tauX = 1024
    tauY = 32
    tauPlus = 64
    tauMinus = 256
    # ---------------------------------
    A2Plus = inputArr[0]
    A2Minus = inputArr[1]
    A3Plus = inputArr[2]
    A3Minus = inputArr[3]
    # ---------------------------------
    r1 = genDE(tauPlus, True, dt)
    r2 = genDE(tauX, True, dt)
    o1 = genDE(tauMinus, False, dt)
    o2 = genDE(tauY, False, dt)
    # ---------------------------------
    syn = Synapse(0, A2Plus, A2Minus, A3Plus, A3Minus)
    synWeight = np.zeros((1, math.floor(totalDuration / dt)))
    # Enumerate through the total runtime
    for timeIndex, currentTime in enumerate(timeToEnumerate):
        # Update the current state of t-pre and t-post
        tpre = (train[0, timeIndex] == 1)
        tpost = (train[1, timeIndex] == 1)
        # Update the current values of r1, r2, o1 and o2
        r1.updateSynapticWeight(tpre, tpost)
        r2.updateSynapticWeight(tpre, tpost)
        o1.updateSynapticWeight(tpre, tpost)
        o2.updateSynapticWeight(tpre, tpost)
        # Update the current synaptic weight
        syn.updateSynapticWeight(tpre, tpost, r1.currentValue,
                                 r2.previousValue, o1.currentValue,
                                 o2.previousValue)
        currentVal = syn.currentWeight
        synWeight[0, timeIndex] = currentVal
    totalWeightChange = synWeight[0, -1] - synWeight[0, 0]
    if (showPlot):
        print('Total Weight Change: [%f]' % (totalWeightChange))
        print('Total Weight Change [n = 60]: [%f]' % (totalWeightChange * 60))
        plt.plot(timeToEnumerate,
                 synWeight[0, :],
                 label='Change in Synaptic Weight')
        plt.legend(loc='lower center')
        plt.title('Change in Synaptic Weight')
        plt.xlim([0, totalDuration])
        plt.show()
    return totalWeightChange * iterations
def runSimulation(inputArr):
    # Initialize the time steps required to emulate the total runtime iteratively
    totalDuration = 1000  # Total duration to run
    dt = 1  # Time between iterations
    timeToEnumerate = np.arange(1, totalDuration + 1, 1)  # Determine the time-step array [0, 0.125, 0.25, 0.375, ..., 800]

    # Generate a random pre-synaptic and post-synaptic spike train to send to the network
    trainGen = GenSpikeTrain(math.floor(totalDuration/dt))
    preTrain = trainGen.SpikeTrainGen()
    postTrain = trainGen.SpikeTrainGen()
    train = np.vstack((preTrain, postTrain))

    # Assign initial parameters
    # ---------------------------------
    tauX = 575
    tauY = 47
    tauPlus = 16.8
    tauMinus = 33.7
    # ---------------------------------
    A2Plus = inputArr[0]
    A2Minus = inputArr[1]
    A3Plus = inputArr[2]
    A3Minus = inputArr[3]
    # ---------------------------------
    r1 = genDE(tauPlus, True, dt)
    r2 = genDE(tauX, True, dt)
    o1 = genDE(tauMinus, False, dt)
    o2 = genDE(tauY, False, dt)
    # ---------------------------------
    syn = Synapse(0, A2Plus, A2Minus, A3Plus, A3Minus)
    # ---------------------------------
    synWeight = np.zeros(math.floor(totalDuration/dt))

    # Enumerate through the total runtime
    for timeIndex, currentTime in enumerate(timeToEnumerate):
        # Update the current state of t-pre and t-post
        tpre = (train[0, timeIndex] == 1)
        tpost = (train[1, timeIndex] == 1)
        # Update the current values of r1, r2, o1 and o2
        r1.updateSynapticWeight(tpre, tpost)
        r2.updateSynapticWeight(tpre, tpost)
        o1.updateSynapticWeight(tpre, tpost)
        o2.updateSynapticWeight(tpre, tpost)

        # Update the current synaptic weight
        syn.updateSynapticWeight(tpre, tpost, r1.currentValue, r2.currentValue, o1.currentValue, o2.currentValue)
        currentVal = syn.currentWeight
        synWeight[timeIndex] = currentVal

    totalWeightChange = synWeight[-1] - synWeight[0]
    print('Total Weight Change: [%f]' % (totalWeightChange))
    plt.plot(timeToEnumerate, synWeight)
    plt.title('Change in Synaptic Weight for Random Spike Train Inputs')
    plt.xlim([0,500])
    plt.show()