import numpy as np, konstanter as k, scipy.optimize as sco

def x_iso(V_iso = 1,V_mb = 1, usikkerhet = False):
    # Brukes til å beregne molfraksjoner til kalibreringskurven

    V_iso = np.array(V_iso)
    V_mb = np.array(V_mb)

    mol_iso = k.roh_iso * V_iso / k.Mm_iso
    mol_mb = k.roh_mb * V_mb / k.Mm_mb
    
    if usikkerhet:
        s_mol_iso = (k.roh_iso / k.Mm_iso) * k.s_V
        s_mol_mb = (k.roh_iso / k.Mm_mb) * k.s_V

        s_x_iso = np.sqrt(((mol_mb / ((mol_iso + mol_mb) ** 2)) * s_mol_iso) ** 2 +
                          ((-mol_iso / ((mol_iso + mol_mb) ** 2)) * s_mol_mb) ** 2)
        return mol_iso/(mol_iso+mol_mb), s_x_iso
    
    return mol_iso/(mol_iso+mol_mb)

def x_mb(V_mb = 1,V_iso = 1, usikkerhet = False):
    # Brukes til å beregne molfraksjoner til kalibreringskurven
    V_mb = np.array(V_mb)
    V_iso = np.array(V_iso)

    mol_mb = k.roh_mb * V_mb / k.Mm_mb
    mol_iso = k.roh_iso * V_iso / k.Mm_iso
    
    if usikkerhet:
        s_mol_mb = (k.roh_mb / k.Mm_mb) * k.s_V
        s_mol_iso = (k.roh_mb / k.Mm_iso) * k.s_V

        s_x_mb = np.sqrt(((mol_iso / ((mol_mb + mol_iso) ** 2)) * s_mol_mb) ** 2 +
                          ((-mol_mb / ((mol_mb + mol_iso) ** 2)) * s_mol_iso) ** 2)
        return mol_mb/(mol_mb+mol_iso), s_x_mb
    
    return mol_mb/(mol_mb+mol_iso)

def aktivitetskoeff(y = list, s_y = 0, x = list, s_x = 0, T = list, p = list, komponent = 'iso'):
    # regner ut aktivitetskoeffisienter fra likning 4.15 i labheftet
    if komponent == 'iso':
        koeff = np.exp((k.H_vap_iso/k.R) * ((1/T) - (1/k.T_b_iso))) * ((p * y)/(k.p0 * x))
        usikkerhet = np.sqrt(
            ((np.exp((k.H_vap_iso / k.R) * ((1 / T) - (1 / k.T_b_iso))) *
                     ((p * y) / (k.p0 * x)) *
                     (-k.H_vap_iso/(k.R * (T**2)))) * k.s_T)**2 +
            ((np.exp((k.H_vap_iso / k.R) * ((1 / T) - (1 / k.T_b_iso))) *
                     ((p * y) / (k.p0 * x)) *
                     (k.H_vap_iso/(k.R * (k.T_b_iso**2)))) * k.s_T)**2 +
            ((np.exp((k.H_vap_iso/k.R) * ((1/T) - (1/k.T_b_iso))) * ((p )/(k.p0 * x))) * s_y)**2 +
            ((np.exp((k.H_vap_iso/k.R) * ((1/T) - (1/k.T_b_iso))) * (-(p * y)/(k.p0 * (x**2)))) * s_x)**2)
        return koeff, usikkerhet

    if komponent == 'mb':
        koeff = np.exp((k.H_vap_mb / k.R) * ((1 / T) - (1 / k.T_b_mb))) * ((p * y) / (k.p0 * x))
        usikkerhet = np.sqrt(
            ((np.exp((k.H_vap_mb / k.R) * ((1 / T) - (1 / k.T_b_mb))) *
              ((p * y) / (k.p0 * x)) *
              (-k.H_vap_mb / (k.R * (T ** 2)))) * k.s_T) ** 2 +
            ((np.exp((k.H_vap_mb / k.R) * ((1 / T) - (1 / k.T_b_mb))) *
              ((p * y) / (k.p0 * x)) *
              (k.H_vap_mb / (k.R * (k.T_b_mb ** 2)))) * k.s_T) ** 2 +
            ((np.exp((k.H_vap_mb / k.R) * ((1 / T) - (1 / k.T_b_mb))) * ((p) / (k.p0 * x))) * s_y) ** 2 +
            ((np.exp((k.H_vap_mb / k.R) * ((1 / T) - (1 / k.T_b_mb))) * (-(p * y) / (k.p0 * (x ** 2)))) * s_x) ** 2)
        return koeff, usikkerhet

def standardavvik(punkter):
    # beregner gjennomsnitt og standardavvik for en liste med tall

    punkter = np.array(punkter)
    snitt = sum(punkter)/len(punkter)

    avvik = punkter - snitt

    snitt_avvik = sum(abs(avvik))/len(avvik)

    std_avvik = np.sqrt(sum((avvik-snitt_avvik)**2)/(len(avvik)))
    return std_avvik, snitt

def usikkerhet_aktivitetskoeffisient(y = list, s_y = 0, x = list, s_x = 0, T = list, p = list, komponent = 'iso'):
        usikkerhet = np.sqrt(
            ((np.exp((k.H_vap_iso / k.R) * ((1 / T) - (1 / k.T_b_iso))) *
                     ((p * y) / (k.p0 * x)) *
                     (-k.H_vap_iso/(k.R * (T**2)))) * k.s_T)**2 +
            ((np.exp((k.H_vap_iso / k.R) * ((1 / T) - (1 / k.T_b_iso))) *
                     ((p * y) / (k.p0 * x)) *
                     (k.H_vap_iso/(k.R * (k.T_b_iso**2)))) * k.s_T)**2 +
            ((np.exp((k.H_vap_iso/k.R) * ((1/T) - (1/k.T_b_iso))) * ((p )/(k.p0 * x))) * s_y)**2 +
            ((np.exp((k.H_vap_iso/k.R) * ((1/T) - (1/k.T_b_iso))) * (-(p * y)/(k.p0 * (x**2)))) * s_x)**2)