Instruction:
Write a Python 3 script to
define the saturated line T = f P

Response:
def _TSat_P(P):
    """Define the saturated line, T=f(P)

    Parameters
    ----------
    P : float
        Pressure, [MPa]

    Returns
    -------
    T : float
        Temperature, [K]

    Notes
    ------
    Raise :class:`NotImplementedError` if input isn't in limit:

        * 0.00061121 ≤ P ≤ 22.064

    References
    ----------
    IAPWS, Revised Release on the IAPWS Industrial Formulation 1997 for the
    Thermodynamic Properties of Water and Steam August 2007,
    http://www.iapws.org/relguide/IF97-Rev.html, Eq 31

    Examples
    --------
    >>> _TSat_P(10)
    584.149488
    """
    # Check input parameters
    if P < 611.212677/1e6 or P > 22.064:
        raise NotImplementedError("Incoming out of bound")

    n = [0, 0.11670521452767E+04, -0.72421316703206E+06, -0.17073846940092E+02,
         0.12020824702470E+05, -0.32325550322333E+07, 0.14915108613530E+02,
         -0.48232657361591E+04, 0.40511340542057E+06, -0.23855557567849E+00,
         0.65017534844798E+03]
    beta = P**0.25
    E = beta**2+n[3]*beta+n[6]
    F = n[1]*beta**2+n[4]*beta+n[7]
    G = n[2]*beta**2+n[5]*beta+n[8]
    D = 2*G/(-F-(F**2-4*E*G)**0.5)
    return (n[10]+D-((n[10]+D)**2-4*(n[9]+n[10]*D))**0.5)/2


Instruction:
Can you tell what is the following Python 3 function doing
def _PSat_h(h):
    # Check input parameters
    hmin_Ps3 = _Region1(623.15, Ps_623)["h"]
    hmax_Ps3 = _Region2(623.15, Ps_623)["h"]
    if h < hmin_Ps3 or h > hmax_Ps3:
        raise NotImplementedError("Incoming out of bound")

    nu = h/2600
    I = [0, 1, 1, 1, 1, 5, 7, 8, 14, 20, 22, 24, 28, 36]
    J = [0, 1, 3, 4, 36, 3, 0, 24, 16, 16, 3, 18, 8, 24]
    n = [0.600073641753024, -0.936203654849857e1, 0.246590798594147e2,
         -0.107014222858224e3, -0.915821315805768e14, -0.862332011700662e4,
         -0.235837344740032e2, 0.252304969384128e18, -0.389718771997719e19,
         -0.333775713645296e23, 0.356499469636328e11, -0.148547544720641e27,
         0.330611514838798e19, 0.813641294467829e38]

    suma = 0
    for i, j, ni in zip(I, J, n):
        suma += ni * (nu-1.02)**i * (nu-0.608)**j
    return 22*suma

Response: Define the saturated line P for region 3


Instruction:
Explain what the following Python 3 code does
def _PSat_s(s):
    # Check input parameters
    smin_Ps3 = _Region1(623.15, Ps_623)["s"]
    smax_Ps3 = _Region2(623.15, Ps_623)["s"]
    if s < smin_Ps3 or s > smax_Ps3:
        raise NotImplementedError("Incoming out of bound")

    sigma = s/5.2
    I = [0, 1, 1, 4, 12, 12, 16, 24, 28, 32]
    J = [0, 1, 32, 7, 4, 14, 36, 10, 0, 18]
    n = [0.639767553612785, -0.129727445396014e2, -0.224595125848403e16,
         0.177466741801846e7, 0.717079349571538e10, -0.378829107169011e18,
         -0.955586736431328e35, 0.187269814676188e24, 0.119254746466473e12,
         0.110649277244882e37]

    suma = 0
    for i, j, ni in zip(I, J, n):
        suma += ni * (sigma-1.03)**i * (sigma-0.699)**j
    return 22*suma

Response: Define the saturated line P = f ( s ) for region 3


Instruction:
Make a summary of the following Python 3 code
def _h2ab_s(s):
    # Check input parameters
    if s < 5.85 or s > 9.155759395:
        raise NotImplementedError("Incoming out of bound")

    sigma1 = s/5.21
    sigma2 = s/9.2
    I = [1, 1, 2, 2, 4, 4, 7, 8, 8, 10, 12, 12, 18, 20, 24, 28, 28, 28, 28, 28,
         32, 32, 32, 32, 32, 36, 36, 36, 36, 36]
    J = [8, 24, 4, 32, 1, 2, 7, 5, 12, 1, 0, 7, 10, 12, 32, 8, 12, 20, 22, 24,
         2, 7, 12, 14, 24, 10, 12, 20, 22, 28]
    n = [-0.524581170928788e3, -0.926947218142218e7, -0.237385107491666e3,
         0.210770155812776e11, -0.239494562010986e2, 0.221802480294197e3,
         -0.510472533393438e7, 0.124981396109147e7, 0.200008436996201e10,
         -0.815158509791035e3, -0.157612685637523e3, -0.114200422332791e11,
         0.662364680776872e16, -0.227622818296144e19, -0.171048081348406e32,
         0.660788766938091e16, 0.166320055886021e23, -0.218003784381501e30,
         -0.787276140295618e30, 0.151062329700346e32, 0.795732170300541e7,
         0.131957647355347e16, -0.325097068299140e24, -0.418600611419248e26,
         0.297478906557467e35, -0.953588761745473e20, 0.166957699620939e25,
         -0.175407764869978e33, 0.347581490626396e35, -0.710971318427851e39]

    suma = 0
    for i, j, ni in zip(I, J, n):
        suma += ni * (1/sigma1-0.513)**i * (sigma2-0.524)**j
    return 2800*exp(suma)

Response: Define the saturated line boundary between Region 4 and 2a - 2b


Instruction:
Here you have a function in Python 3, explain what it does
def _Region1(T, P):
    if P < 0:
        P = Pmin

    I = [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 4,
         4, 4, 5, 8, 8, 21, 23, 29, 30, 31, 32]
    J = [-2, -1, 0, 1, 2, 3, 4, 5, -9, -7, -1, 0, 1, 3, -3, 0, 1, 3, 17, -4, 0,
         6, -5, -2, 10, -8, -11, -6, -29, -31, -38, -39, -40, -41]
    n = [0.14632971213167, -0.84548187169114, -0.37563603672040e1,
         0.33855169168385e1, -0.95791963387872, 0.15772038513228,
         -0.16616417199501e-1, 0.81214629983568e-3, 0.28319080123804e-3,
         -0.60706301565874e-3, -0.18990068218419e-1, -0.32529748770505e-1,
         -0.21841717175414e-1, -0.52838357969930e-4, -0.47184321073267e-3,
         -0.30001780793026e-3, 0.47661393906987e-4, -0.44141845330846e-5,
         -0.72694996297594e-15, -0.31679644845054e-4, -0.28270797985312e-5,
         -0.85205128120103e-9, -0.22425281908000e-5, -0.65171222895601e-6,
         -0.14341729937924e-12, -0.40516996860117e-6, -0.12734301741641e-8,
         -0.17424871230634e-9, -0.68762131295531e-18, 0.14478307828521e-19,
         0.26335781662795e-22, -0.11947622640071e-22, 0.18228094581404e-23,
         -0.93537087292458e-25]
    Tr = 1386/T
    Pr = P/16.53
    g = gp = gpp = gt = gtt = gpt = 0
    for i, j, ni in zip(I, J, n):
        g += ni * (7.1-Pr)**i * (Tr-1.222)**j
        gp -= ni*i * (7.1-Pr)**(i-1) * (Tr-1.222)**j
        gpp += ni*i*(i-1) * (7.1-Pr)**(i-2) * (Tr-1.222)**j
        gt += ni*j * (7.1-Pr)**i * (Tr-1.222)**(j-1)
        gtt += ni*j*(j-1) * (7.1-Pr)**i * (Tr-1.222)**(j-2)
        gpt -= ni*i*j * (7.1-Pr)**(i-1) * (Tr-1.222)**(j-1)

    propiedades = {}
    propiedades["T"] = T
    propiedades["P"] = P
    propiedades["v"] = Pr*gp*R*T/P/1000
    propiedades["h"] = Tr*gt*R*T
    propiedades["s"] = R*(Tr*gt-g)
    propiedades["cp"] = -R*Tr**2*gtt
    propiedades["cv"] = R*(-Tr**2*gtt+(gp-Tr*gpt)**2/gpp)
    propiedades["w"] = sqrt(R*T*1000*gp**2/((gp-Tr*gpt)**2/(Tr**2*gtt)-gpp))
    propiedades["alfav"] = (1-Tr*gpt/gp)/T
    propiedades["kt"] = -Pr*gpp/gp/P
    propiedades["region"] = 1
    propiedades["x"] = 0
    return propiedades

Response: Basic equation for region 1


Instruction:
How would you explain what the following Python 3 function does
def Region2_cp0(Tr, Pr):
    Jo = [0, 1, -5, -4, -3, -2, -1, 2, 3]
    no = [-0.96927686500217E+01, 0.10086655968018E+02, -0.56087911283020E-02,
          0.71452738081455E-01, -0.40710498223928E+00, 0.14240819171444E+01,
          -0.43839511319450E+01, -0.28408632460772E+00, 0.21268463753307E-01]
    go = log(Pr)
    gop = Pr**-1
    gopp = -Pr**-2
    got = gott = gopt = 0
    for j, ni in zip(Jo, no):
        go += ni * Tr**j
        got += ni*j * Tr**(j-1)
        gott += ni*j*(j-1) * Tr**(j-2)
    return go, gop, gopp, got, gott, gopt

Response: Ideal properties for region 2


Instruction:
How would you code a function in Python 3 to
define the boundary between Region 2a and 2b h = f ( s

Response:
def _hab_s(s):
    """Define the boundary between Region 2a and 2b, h=f(s)

    Parameters
    ----------
    s : float
        Specific entropy, [kJ/kgK]

    Returns
    -------
    h : float
        Specific enthalpy, [kJ/kg]

    References
    ----------
    IAPWS, Revised Supplementary Release on Backward Equations for Pressure
    as a Function of Enthalpy and Entropy p(h,s) for Regions 1 and 2 of the
    IAPWS Industrial Formulation 1997 for the Thermodynamic Properties of
    Water and Steam, http://www.iapws.org/relguide/Supp-PHS12-2014.pdf, Eq 2

    Examples
    --------
    >>> _hab_s(7)
    3376.437884
    """
    smin = _Region2(_TSat_P(4), 4)["s"]
    smax = _Region2(1073.15, 4)["s"]
    if s < smin:
        h = 0
    elif s > smax:
        h = 5000
    else:
        h = -0.349898083432139e4 + 0.257560716905876e4*s - \
            0.421073558227969e3*s**2+0.276349063799944e2*s**3
    return h


Instruction:
Here you have a function in Python 3, explain what it does
def _Backward2_T_Ph(P, h):
    if P <= 4:
        T = _Backward2a_T_Ph(P, h)
    elif 4 < P <= 6.546699678:
        T = _Backward2b_T_Ph(P, h)
    else:
        hf = _hbc_P(P)
        if h >= hf:
            T = _Backward2b_T_Ph(P, h)
        else:
            T = _Backward2c_T_Ph(P, h)

    if P <= 22.064:
        Tsat = _TSat_P(P)
        T = max(Tsat, T)
    return T

Response: Backward equation for region 2 T = f P h


Instruction:
Can you generate the documentation for the following Python 3 function
def _Backward2_T_Ps(P, s):
    if P <= 4:
        T = _Backward2a_T_Ps(P, s)
    elif s >= 5.85:
        T = _Backward2b_T_Ps(P, s)
    else:
        T = _Backward2c_T_Ps(P, s)

    if P <= 22.064:
        Tsat = _TSat_P(P)
        T = max(Tsat, T)
    return T

Response: Backward equation for region 2 T = f P s


Instruction:
How would you code a function in Python 3 to
define the boundary between Region 3a - 3b T = f ( P )

Response:
def _tab_P(P):
    """Define the boundary between Region 3a-3b, T=f(P)

    Parameters
    ----------
    P : float
        Pressure, [MPa]

    Returns
    -------
    T : float
        Temperature, [K]

    References
    ----------
    IAPWS, Revised Supplementary Release on Backward Equations for Specific
    Volume as a Function of Pressure and Temperature v(p,T) for Region 3 of the
    IAPWS Industrial Formulation 1997 for the Thermodynamic Properties of Water
    and Steam, http://www.iapws.org/relguide/Supp-VPT3-2016.pdf, Eq. 2

    Examples
    --------
    >>> _tab_P(40)
    693.0341408
    """
    I = [0, 1, 2, -1, -2]
    n = [0.154793642129415e4, -0.187661219490113e3, 0.213144632222113e2,
         -0.191887498864292e4, 0.918419702359447e3]

    Pr = P/1
    T = 0
    for i, ni in zip(I, n):
        T += ni * log(Pr)**i
    return T


Instruction:
Given the following Python 3 function, write the documentation
def _txx_P(P, xy):
    ng = {
        "cd": [0.585276966696349e3, 0.278233532206915e1, -0.127283549295878e-1,
               0.159090746562729e-3],
        "gh": [-0.249284240900418e5, 0.428143584791546e4, -0.269029173140130e3,
               0.751608051114157e1, -0.787105249910383e-1],
        "ij": [0.584814781649163e3, -0.616179320924617, 0.260763050899562,
               -0.587071076864459e-2, 0.515308185433082e-4],
        "jk": [0.617229772068439e3, -0.770600270141675e1, 0.697072596851896,
               -0.157391839848015e-1, 0.137897492684194e-3],
        "mn": [0.535339483742384e3, 0.761978122720128e1, -0.158365725441648,
               0.192871054508108e-2],
        "qu": [0.565603648239126e3, 0.529062258221222e1, -0.102020639611016,
               0.122240301070145e-2],
        "rx": [0.584561202520006e3, -0.102961025163669e1, 0.243293362700452,
               -0.294905044740799e-2],
        "uv": [0.528199646263062e3, 0.890579602135307e1, -0.222814134903755,
               0.286791682263697e-2]}

    n = ng[xy]
    Pr = P/1
    T = 0
    for i, ni in enumerate(n):
        T += ni * Pr**i
    return T

Response: Define the boundary between 3x - 3y T = f ( P xy )


Instruction:
Can you generate a brief explanation for the following Python 3 code
def _Backward3a_v_Ph(P, h):
    I = [-12, -12, -12, -12, -10, -10, -10, -8, -8, -6, -6, -6, -4, -4, -3, -2,
         -2, -1, -1, -1, -1, 0, 0, 1, 1, 1, 2, 2, 3, 4, 5, 8]
    J = [6, 8, 12, 18, 4, 7, 10, 5, 12, 3, 4, 22, 2, 3, 7, 3, 16, 0, 1, 2, 3,
         0, 1, 0, 1, 2, 0, 2, 0, 2, 2, 2]
    n = [0.529944062966028e-2, -0.170099690234461, 0.111323814312927e2,
         -0.217898123145125e4, -0.506061827980875e-3, 0.556495239685324,
         -0.943672726094016e1, -0.297856807561527, 0.939353943717186e2,
         0.192944939465981e-1, 0.421740664704763, -0.368914126282330e7,
         -0.737566847600639e-2, -0.354753242424366, -0.199768169338727e1,
         0.115456297059049e1, 0.568366875815960e4, 0.808169540124668e-2,
         0.172416341519307, 0.104270175292927e1, -0.297691372792847,
         0.560394465163593, 0.275234661176914, -0.148347894866012,
         -0.651142513478515e-1, -0.292468715386302e1, 0.664876096952665e-1,
         0.352335014263844e1, -0.146340792313332e-1, -0.224503486668184e1,
         0.110533464706142e1, -0.408757344495612e-1]

    Pr = P/100
    nu = h/2100
    suma = 0
    for i, j, ni in zip(I, J, n):
        suma += ni * (Pr+0.128)**i * (nu-0.727)**j
    return 0.0028*suma

Response: Backward equation for region 3a v = f ( P h )


Instruction:
Can you tell what is the following Python 3 function doing
def _Backward3_v_Ph(P, h):
    hf = _h_3ab(P)
    if h <= hf:
        return _Backward3a_v_Ph(P, h)
    else:
        return _Backward3b_v_Ph(P, h)

Response: Backward equation for region 3 v = f ( P h )


Instruction:
Explain what the following Python 3 code does
def _Backward3_P_hs(h, s):
    sc = 4.41202148223476
    if s <= sc:
        return _Backward3a_P_hs(h, s)
    else:
        return _Backward3b_P_hs(h, s)

Response: Backward equation for region 3 P = f h s


Instruction:
How would you explain what the following Python 3 function does
def _Backward3x_v_PT(T, P, x):
    par = {
        "a": [0.0024, 100, 760, 0.085, 0.817, 1, 1, 1],
        "b": [0.0041, 100, 860, 0.280, 0.779, 1, 1, 1],
        "c": [0.0022, 40, 690, 0.259, 0.903, 1, 1, 1],
        "d": [0.0029, 40, 690, 0.559, 0.939, 1, 1, 4],
        "e": [0.0032, 40, 710, 0.587, 0.918, 1, 1, 1],
        "f": [0.0064, 40, 730, 0.587, 0.891, 0.5, 1, 4],
        "g": [0.0027, 25, 660, 0.872, 0.971, 1, 1, 4],
        "h": [0.0032, 25, 660, 0.898, 0.983, 1, 1, 4],
        "i": [0.0041, 25, 660, 0.910, 0.984, 0.5, 1, 4],
        "j": [0.0054, 25, 670, 0.875, 0.964, 0.5, 1, 4],
        "k": [0.0077, 25, 680, 0.802, 0.935, 1, 1, 1],
        "l": [0.0026, 24, 650, 0.908, 0.989, 1, 1, 4],
        "m": [0.0028, 23, 650, 1.000, 0.997, 1, 0.25, 1],
        "n": [0.0031, 23, 650, 0.976, 0.997, None, None, None],
        "o": [0.0034, 23, 650, 0.974, 0.996, 0.5, 1, 1],
        "p": [0.0041, 23, 650, 0.972, 0.997, 0.5, 1, 1],
        "q": [0.0022, 23, 650, 0.848, 0.983, 1, 1, 4],
        "r": [0.0054, 23, 650, 0.874, 0.982, 1, 1, 1],
        "s": [0.0022, 21, 640, 0.886, 0.990, 1, 1, 4],
        "t": [0.0088, 20, 650, 0.803, 1.020, 1, 1, 1],
        "u": [0.0026, 23, 650, 0.902, 0.988, 1, 1, 1],
        "v": [0.0031, 23, 650, 0.960, 0.995, 1, 1, 1],
        "w": [0.0039, 23, 650, 0.959, 0.995, 1, 1, 4],
        "x": [0.0049, 23, 650, 0.910, 0.988, 1, 1, 1],
        "y": [0.0031, 22, 650, 0.996, 0.994, 1, 1, 4],
        "z": [0.0038, 22, 650, 0.993, 0.994, 1, 1, 4],
        }

    I = {
        "a": [-12, -12, -12, -10, -10, -10, -8, -8, -8, -6, -5, -5, -5, -4, -3,
              -3, -3, -3, -2, -2, -2, -1, -1, -1, 0, 0, 1, 1, 2, 2],
        "b": [-12, -12, -10, -10, -8, -6, -6, -6, -5, -5, -5, -4, -4, -4, -3,
              -3, -3, -3, -3, -2, -2, -2, -1, -1, 0, 0, 1, 1, 2, 3, 4, 4],
        "c": [-12, -12, -12, -10, -10, -10, -8, -8, -8, -6, -5, -5, -5, -4, -4,
              -3, -3, -2, -2, -2, -1, -1, -1, 0, 0, 0, 1, 1, 2, 2, 2, 2, 3, 3,
              8],
        "d": [-12, -12, -12, -12, -12, -12, -10, -10, -10, -10, -10, -10, -10,
              -8, -8, -8, -8, -6, -6, -5, -5, -5, -5, -4, -4, -4, -3, -3, -2,
              -2, -1, -1, -1, 0, 0, 1, 1, 3],
        "e": [-12, -12, -10, -10, -10, -10, -10, -8, -8, -8, -6, -5, -4, -4,
              -3, -3, -3, -2, -2, -2, -2, -1, 0, 0, 1, 1, 1, 2, 2],
        "f": [0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 3, 3, 3, 4, 5, 5, 6, 7, 7,
              10, 12, 12, 12, 14, 14, 14, 14, 14, 16, 16, 18, 18, 20, 20, 20,
              22, 24, 24, 28, 32],
        "g": [-12, -12, -12, -12, -12, -12, -10, -10, -10, -8, -8, -8, -8, -6,
              -6, -5, -5, -4, -3, -2, -2, -2, -2, -1, -1, -1, 0, 0, 0, 1, 1, 1,
              3, 5, 6, 8, 10, 10],
        "h": [-12, -12, -10, -10, -10, -10, -10, -10, -8, -8, -8, -8, -8, -6,
              -6, -6, -5, -5, -5, -4, -4, -3, -3, -2, -1, -1, 0, 1, 1],
        "i": [0, 0, 0, 1, 1, 1, 1, 2, 3, 3, 4, 4, 4, 5, 5, 5, 7, 7, 8, 8, 10,
              12, 12, 12, 14, 14, 14, 14, 18, 18, 18, 18, 18, 20, 20, 22, 24,
              24, 32, 32, 36, 36],
        "j": [0, 0, 0, 1, 1, 1, 2, 2, 3, 4, 4, 5, 5, 5, 6, 10, 12, 12, 14, 14,
              14, 16, 18, 20, 20, 24, 24, 28, 28],
        "k": [-2, -2, -1, -1, 0, -0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2,
              2, 2, 2, 2, 5, 5, 5, 6, 6, 6, 6, 8, 10, 12],
        "l": [-12, -12, -12, -12, -12, -10, -10, -8, -8, -8, -8, -8, -8, -8,
              -6, -5, -5, -4, -4, -3, -3, -3, -3, -2, -2, -2, -1, -1, -1, 0, 0,
              0, 0, 1, 1, 2, 4, 5, 5, 6, 10, 10, 14],
        "m": [0, 3, 8, 20, 1, 3, 4, 5, 1, 6, 2, 4, 14, 2, 5, 3, 0, 1, 1, 1, 28,
              2, 16, 0, 5, 0, 3, 4, 12, 16, 1, 8, 14, 0, 2, 3, 4, 8, 14, 24],
        "n": [0, 3, 4, 6, 7, 10, 12, 14, 18, 0, 3, 5, 6, 8, 12, 0, 3, 7, 12,
              2, 3, 4, 2, 4, 7, 4, 3, 5, 6, 0, 0, 3, 1, 0, 1, 0, 1, 0, 1],
        "o": [0, 0, 0, 2, 3, 4, 4, 4, 4, 4, 5, 5, 6, 7, 8, 8, 8, 10, 10, 14,
              14, 20, 20, 24],
        "p": [0, 0, 0, 0, 1, 2, 3, 3, 4, 6, 7, 7, 8, 10, 12, 12, 12, 14, 14,
              14, 16, 18, 20, 22, 24, 24, 36],
        "q": [-12, -12, -10, -10, -10, -10, -8, -6, -5, -5, -4, -4, -3, -2,
              -2, -2, -2, -1, -1, -1, 0, 1, 1, 1],
        "r": [-8, -8, -3, -3, -3, -3, -3, 0, 0, 0, 0, 3, 3, 8, 8, 8, 8, 10,
              10, 10, 10, 10, 10, 10, 10, 12, 14],
        "s": [-12, -12, -10, -8, -6, -5, -5, -4, -4, -3, -3, -2, -1, -1, -1, 0,
              0, 0, 0, 1, 1, 3, 3, 3, 4, 4, 4, 5, 14],
        "t": [0, 0, 0, 0, 1, 1, 2, 2, 2, 3, 3, 4, 4, 7, 7, 7, 7, 7, 10, 10, 10,
              10, 10, 18, 20, 22, 22, 24, 28, 32, 32, 32, 36],
        "u": [-12, -10, -10, -10, -8, -8, -8, -6, -6, -5, -5, -5, -3, -1, -1,
              -1, -1, 0, 0, 1, 2, 2, 3, 5, 5, 5, 6, 6, 8, 8, 10, 12, 12, 12,
              14, 14, 14, 14],
        "v": [-10, -8, -6, -6, -6, -6, -6, -6, -5, -5, -5, -5, -5, -5, -4, -4,
              -4, -4, -3, -3, -3, -2, -2, -1, -1, 0, 0, 0, 1, 1, 3, 4, 4, 4, 5,
              8, 10, 12, 14],
        "w": [-12, -12, -10, -10, -8, -8, -8, -6, -6, -6, -6, -5, -4, -4, -3,
              -3, -2, -2, -1, -1, -1, 0, 0, 1, 2, 2, 3, 3, 5, 5, 5, 8, 8, 10,
              10],
        "x": [-8, -6, -5, -4, -4, -4, -3, -3, -1, 0, 0, 0, 1, 1, 2, 3, 3, 3, 4,
              5, 5, 5, 6, 8, 8, 8, 8, 10, 12, 12, 12, 12, 14, 14, 14, 14],
        "y": [0, 0, 0, 0, 1, 2, 2, 2, 2, 3, 3, 3, 4, 4, 5, 5, 8, 8, 10, 12],
        "z": [-8, -6, -5, -5, -4, -4, -4, -3, -3, -3, -2, -1, 0, 1, 2, 3, 3, 6,
              6, 6, 6, 8, 8]}

    J = {
        "a": [5, 10, 12, 5, 10, 12, 5, 8, 10, 1, 1, 5, 10, 8, 0, 1, 3, 6, 0,
              2, 3, 0, 1, 2, 0, 1, 0, 2, 0, 2],
        "b": [10, 12, 8, 14, 8, 5, 6, 8, 5, 8, 10, 2, 4, 5, 0, 1, 2, 3, 5, 0,
              2, 5, 0, 2, 0, 1, 0, 2, 0, 2, 0, 1],
        "c": [6, 8, 10, 6, 8, 10, 5, 6, 7, 8, 1, 4, 7, 2, 8, 0, 3, 0, 4, 5, 0,
              1, 2, 0, 1, 2, 0, 2, 0, 1, 3, 7, 0, 7, 1],
        "d": [4, 6, 7, 10, 12, 16, 0, 2, 4, 6, 8, 10, 14, 3, 7, 8, 10, 6, 8, 1,
              2, 5, 7, 0, 1, 7, 2, 4, 0, 1, 0, 1, 5, 0, 2, 0, 6, 0],
        "e": [14, 16, 3, 6, 10, 14, 16, 7, 8, 10, 6, 6, 2, 4, 2, 6, 7, 0, 1,
              3, 4, 0, 0, 1, 0, 4, 6, 0, 2],
        "f": [-3, -2, -1, 0, 1, 2, -1, 1, 2, 3, 0, 1, -5, -2, 0, -3, -8, 1, -6,
              -4, 1, -6, -10, -8, -4, -12, -10, -8, -6, -4, -10, -8, -12, -10,
              -12, -10, -6, -12, -12, -4, -12, -12],
        "g": [7, 12, 14, 18, 22, 24, 14, 20, 24, 7, 8, 10, 12, 8, 22, 7, 20,
              22, 7, 3, 5, 14, 24, 2, 8, 18, 0, 1, 2, 0, 1, 3, 24, 22, 12, 3,
              0, 6],
        "h": [8, 12, 4, 6, 8, 10, 14, 16, 0, 1, 6, 7, 8, 4, 6, 8, 2, 3, 4, 2,
              4, 1, 2, 0, 0, 2, 0, 0, 2],
        "i": [0, 1, 10, -4, -2, -1, 0, 0, -5, 0, -3, -2, -1, -6, -1, 12, -4,
              -3, -6, 10, -8, -12, -6, -4, -10, -8, -4, 5, -12, -10, -8, -6,
              2, -12, -10, -12, -12, -8, -10, -5, -10, -8],
        "j": [-1, 0, 1, -2, -1, 1, -1, 1, -2, -2, 2, -3, -2, 0, 3, -6, -8, -3,
              -10, -8, -5, -10, -12, -12, -10, -12, -6, -12, -5],
        "k": [10, 12, -5, 6, -12, -6, -2, -1, 0, 1, 2, 3, 14, -3, -2, 0, 1, 2,
              -8, -6, -3, -2, 0, 4, -12, -6, -3, -12, -10, -8, -5, -12, -12,
              -10],
        "l": [14, 16, 18, 20, 22, 14, 24, 6, 10, 12, 14, 18, 24, 36, 8, 4, 5,
              7, 16, 1, 3, 18, 20, 2, 3, 10, 0, 1, 3, 0, 1, 2, 12, 0, 16, 1, 0,
              0, 1, 14, 4, 12, 10],
        "m": [0, 0, 0, 2, 5, 5, 5, 5, 6, 6, 7, 8, 8, 10, 10, 12, 14, 14, 18,
              20, 20, 22, 22, 24, 24, 28, 28, 28, 28, 28, 32, 32, 32, 36, 36,
              36, 36, 36, 36, 36],
        "n": [-12, -12, -12, -12, -12, -12, -12, -12, -12, -10, -10, -10, -10,
              -10, -10, -8, -8, -8, -8, -6, -6, -6, -5, -5, -5, -4, -3, -3,
              -3, -2, -1, -1, 0, 1, 1, 2, 4, 5, 6],
        "o": [-12, -4, -1, -1, -10, -12, -8, -5, -4, -1, -4, -3, -8, -12, -10,
              -8, -4, -12, -8, -12, -8, -12, -10, -12],
        "p": [-1, 0, 1, 2, 1, -1, -3, 0, -2, -2, -5, -4, -2, -3, -12, -6, -5,
              -10, -8, -3, -8, -8, -10, -10, -12, -8, -12],
        "q": [10, 12, 6, 7, 8, 10, 8, 6, 2, 5, 3, 4, 3, 0, 1, 2, 4, 0, 1, 2,
              0, 0, 1, 3],
        "r": [6, 14, -3, 3, 4, 5, 8, -1, 0, 1, 5, -6, -2, -12, -10, -8, -5,
              -12, -10, -8, -6, -5, -4, -3, -2, -12, -12],
        "s": [20, 24, 22, 14, 36, 8, 16, 6, 32, 3, 8, 4, 1, 2, 3, 0, 1, 4, 28,
              0, 32, 0, 1, 2, 3, 18, 24, 4, 24],
        "t": [0, 1, 4, 12, 0, 10, 0, 6, 14, 3, 8, 0, 10, 3, 4, 7, 20, 36, 10,
              12, 14, 16, 22, 18, 32, 22, 36, 24, 28, 22, 32, 36, 36],
        "u": [14, 10, 12, 14, 10, 12, 14, 8, 12, 4, 8, 12, 2, -1, 1, 12, 14,
              -3, 1, -2, 5, 10, -5, -4, 2, 3, -5, 2, -8, 8, -4, -12, -4, 4,
              -12, -10, -6, 6],
        "v": [-8, -12, -12, -3, 5, 6, 8, 10, 1, 2, 6, 8, 10, 14, -12, -10, -6,
              10, -3, 10, 12, 2, 4, -2, 0, -2, 6, 10, -12, -10, 3, -6, 3, 10,
              2, -12, -2, -3, 1],
        "w": [8, 14, -1, 8, 6, 8, 14, -4, -3, 2, 8, -10, -1, 3, -10, 3, 1, 2,
              -8, -4, 1, -12, 1, -1, -1, 2, -12, -5, -10, -8, -6, -12, -10,
              -12, -8],
        "x": [14, 10, 10, 1, 2, 14, -2, 12, 5, 0, 4, 10, -10, -1, 6, -12, 0,
              8, 3, -6, -2, 1, 1, -6, -3, 1, 8, -8, -10, -8, -5, -4, -12, -10,
              -8, -6],
        "y": [-3, 1, 5, 8, 8, -4, -1, 4, 5, -8, 4, 8, -6, 6, -2, 1, -8, -2,
              -5, -8],
        "z": [3, 6, 6, 8, 5, 6, 8, -2, 5, 6, 2, -6, 3, 1, 6, -6, -2, -6, -5,
              -4, -1, -8, -4]}

    n = {
        "a": [0.110879558823853e-2, 0.572616740810616e3, -0.767051948380852e5,
              -0.253321069529674e-1, 0.628008049345689e4, 0.234105654131876e6,
              0.216867826045856, -0.156237904341963e3, -0.269893956176613e5,
              -0.180407100085505e-3, 0.116732227668261e-2, 0.266987040856040e2,
              0.282776617243286e5, -0.242431520029523e4, 0.435217323022733e-3,
              -0.122494831387441e-1, 0.179357604019989e1, 0.442729521058314e2,
              -0.593223489018342e-2, 0.453186261685774, 0.135825703129140e1,
              0.408748415856745e-1, 0.474686397863312, 0.118646814997915e1,
              0.546987265727549, 0.195266770452643, -0.502268790869663e-1,
              -0.369645308193377, 0.633828037528420e-2, 0.797441793901017e-1],
        "b": [-0.827670470003621e-1, 0.416887126010565e2, 0.483651982197059e-1,
              -0.291032084950276e5, -0.111422582236948e3, -.202300083904014e-1,
              0.294002509338515e3, 0.140244997609658e3, -0.344384158811459e3,
              0.361182452612149e3, -0.140699677420738e4, -0.202023902676481e-2,
              0.171346792457471e3, -0.425597804058632e1, 0.691346085000334e-5,
              0.151140509678925e-2, -0.416375290166236e-1, -.413754957011042e2,
              -0.506673295721637e2, -0.572212965569023e-3, 0.608817368401785e1,
              0.239600660256161e2, 0.122261479925384e-1, 0.216356057692938e1,
              0.398198903368642, -0.116892827834085, -0.102845919373532,
              -0.492676637589284, 0.655540456406790e-1, -0.240462535078530,
              -0.269798180310075e-1, 0.128369435967012],
        "c": [0.311967788763030e1, 0.276713458847564e5, 0.322583103403269e8,
              -0.342416065095363e3, -0.899732529907377e6, -0.793892049821251e8,
              0.953193003217388e2, 0.229784742345072e4, 0.175336675322499e6,
              0.791214365222792e7, 0.319933345844209e-4, -0.659508863555767e2,
              -0.833426563212851e6, 0.645734680583292e-1, -0.382031020570813e7,
              0.406398848470079e-4, 0.310327498492008e2, -0.892996718483724e-3,
              0.234604891591616e3, 0.377515668966951e4, 0.158646812591361e-1,
              0.707906336241843, 0.126016225146570e2, 0.736143655772152,
              0.676544268999101, -0.178100588189137e2, -0.156531975531713,
              0.117707430048158e2, 0.840143653860447e-1, -0.186442467471949,
              -0.440170203949645e2, 0.123290423502494e7, -0.240650039730845e-1,
              -0.107077716660869e7, 0.438319858566475e-1],
        "d": [-0.452484847171645e-9, .315210389538801e-4, -.214991352047545e-2,
              0.508058874808345e3, -0.127123036845932e8, 0.115371133120497e13,
              -.197805728776273e-15, .241554806033972e-10,
              -.156481703640525e-5, 0.277211346836625e-2, -0.203578994462286e2,
              0.144369489909053e7, -0.411254217946539e11, 0.623449786243773e-5,
              -.221774281146038e2, -0.689315087933158e5, -0.195419525060713e8,
              0.316373510564015e4, 0.224040754426988e7, -0.436701347922356e-5,
              -.404213852833996e-3, -0.348153203414663e3, -0.385294213555289e6,
              0.135203700099403e-6, 0.134648383271089e-3, 0.125031835351736e6,
              0.968123678455841e-1, 0.225660517512438e3, -0.190102435341872e-3,
              -.299628410819229e-1, 0.500833915372121e-2, 0.387842482998411,
              -0.138535367777182e4, 0.870745245971773, 0.171946252068742e1,
              -.326650121426383e-1, 0.498044171727877e4, 0.551478022765087e-2],
        "e": [0.715815808404721e9, -0.114328360753449e12, .376531002015720e-11,
              -0.903983668691157e-4, 0.665695908836252e6, 0.535364174960127e10,
              0.794977402335603e11, 0.922230563421437e2, -0.142586073991215e6,
              -0.111796381424162e7, 0.896121629640760e4, -0.669989239070491e4,
              0.451242538486834e-2, -0.339731325977713e2, -0.120523111552278e1,
              0.475992667717124e5, -0.266627750390341e6, -0.153314954386524e-3,
              0.305638404828265, 0.123654999499486e3, -0.104390794213011e4,
              -0.157496516174308e-1, 0.685331118940253, 0.178373462873903e1,
              -0.544674124878910, 0.204529931318843e4, -0.228342359328752e5,
              0.413197481515899, -0.341931835910405e2],
        "f": [-0.251756547792325e-7, .601307193668763e-5, -.100615977450049e-2,
              0.999969140252192, 0.214107759236486e1, -0.165175571959086e2,
              -0.141987303638727e-2, 0.269251915156554e1, 0.349741815858722e2,
              -0.300208695771783e2, -0.131546288252539e1, -0.839091277286169e1,
              0.181545608337015e-9, -0.591099206478909e-3, 0.152115067087106e1,
              0.252956470663225e-4, 0.100726265203786e-14, -0.14977453386065e1,
              -0.793940970562969e-9, -0.150290891264717e-3, .151205531275133e1,
              0.470942606221652e-5, .195049710391712e-12, -.911627886266077e-8,
              .604374640201265e-3, -.225132933900136e-15, .610916973582981e-11,
              -.303063908043404e-6, -.137796070798409e-4, -.919296736666106e-3,
              .639288223132545e-9, .753259479898699e-6, -0.400321478682929e-12,
              .756140294351614e-8, -.912082054034891e-11, -.237612381140539e-7,
              0.269586010591874e-4, -.732828135157839e-10, .241995578306660e-9,
              -.405735532730322e-3, .189424143498011e-9, -.486632965074563e-9],
        "g": [0.412209020652996e-4, -0.114987238280587e7, 0.948180885032080e10,
              -0.195788865718971e18, 0.4962507048713e25, -0.105549884548496e29,
              -0.758642165988278e12, -.922172769596101e23, .725379072059348e30,
              -0.617718249205859e2, 0.107555033344858e5, -0.379545802336487e8,
              0.228646846221831e12, -0.499741093010619e7, -.280214310054101e31,
              0.104915406769586e7, 0.613754229168619e28, 0.802056715528378e32,
              -0.298617819828065e8, -0.910782540134681e2, 0.135033227281565e6,
              -0.712949383408211e19, -0.104578785289542e37, .304331584444093e2,
              0.593250797959445e10, -0.364174062110798e28, 0.921791403532461,
              -0.337693609657471, -0.724644143758508e2, -0.110480239272601,
              0.536516031875059e1, -0.291441872156205e4, 0.616338176535305e40,
              -0.120889175861180e39, 0.818396024524612e23, 0.940781944835829e9,
              -0.367279669545448e5, -0.837513931798655e16],
        "h": [0.561379678887577e-1, 0.774135421587083e10, 0.111482975877938e-8,
              -0.143987128208183e-2, 0.193696558764920e4, -0.605971823585005e9,
              0.171951568124337e14, -.185461154985145e17, 0.38785116807801e-16,
              -.395464327846105e-13, -0.170875935679023e3, -0.21201062070122e4,
              0.177683337348191e8, 0.110177443629575e2, -0.234396091693313e6,
              -0.656174421999594e7, 0.156362212977396e-4, -0.212946257021400e1,
              0.135249306374858e2, 0.177189164145813, 0.139499167345464e4,
              -0.703670932036388e-2, -0.152011044389648, 0.981916922991113e-4,
              0.147199658618076e-2, 0.202618487025578e2, 0.899345518944240,
              -0.211346402240858, 0.249971752957491e2],
        "i": [0.106905684359136e1, -0.148620857922333e1, 0.259862256980408e15,
              -.446352055678749e-11, -.566620757170032e-6,
              -.235302885736849e-2, -0.269226321968839, 0.922024992944392e1,
              0.357633505503772e-11, -.173942565562222e2, 0.700681785556229e-5,
              -.267050351075768e-3, -.231779669675624e1, -.753533046979752e-12,
              .481337131452891e1, -0.223286270422356e22, -.118746004987383e-4,
              .646412934136496e-2, -0.410588536330937e-9, .422739537057241e20,
              .313698180473812e-12, 0.16439533434504e-23, -.339823323754373e-5,
              -.135268639905021e-1, -.723252514211625e-14, .184386437538366e-8,
              -.463959533752385e-1, -.99226310037675e14, .688169154439335e-16,
              -.222620998452197e-10, -.540843018624083e-7, .345570606200257e-2,
              .422275800304086e11, -.126974478770487e-14, .927237985153679e-9,
              .612670812016489e-13, -.722693924063497e-11,
              -.383669502636822e-3, .374684572410204e-3, -0.931976897511086e5,
              -0.247690616026922e-1, .658110546759474e2],
        "j": [-0.111371317395540e-3, 0.100342892423685e1, 0.530615581928979e1,
              0.179058760078792e-5, -0.728541958464774e-3, -.187576133371704e2,
              0.199060874071849e-2, 0.243574755377290e2, -0.177040785499444e-3,
              -0.25968038522713e-2, -0.198704578406823e3, 0.738627790224287e-4,
              -0.236264692844138e-2, -0.161023121314333e1, 0.622322971786473e4,
              -.960754116701669e-8, -.510572269720488e-10, .767373781404211e-2,
              .663855469485254e-14, -.717590735526745e-9, 0.146564542926508e-4,
              .309029474277013e-11, -.464216300971708e-15,
              -.390499637961161e-13, -.236716126781431e-9,
              .454652854268717e-11, -.422271787482497e-2,
              0.283911742354706e-10, 0.270929002720228e1],
        "k": [-0.401215699576099e9, 0.484501478318406e11, .394721471363678e-14,
              .372629967374147e5, -.369794374168666e-29, -.380436407012452e-14,
              0.475361629970233e-6, -0.879148916140706e-3, 0.844317863844331,
              0.122433162656600e2, -0.104529634830279e3, 0.589702771277429e3,
              -.291026851164444e14, .170343072841850e-5, -0.277617606975748e-3,
              -0.344709605486686e1, 0.221333862447095e2, -0.194646110037079e3,
              .808354639772825e-15, -.18084520914547e-10, -.696664158132412e-5,
              -0.181057560300994e-2, 0.255830298579027e1, 0.328913873658481e4,
              -.173270241249904e-18, -.661876792558034e-6, -.39568892342125e-2,
              .604203299819132e-17, -.400879935920517e-13, .160751107464958e-8,
              .383719409025556e-4, -.649565446702457e-14, -.149095328506e-11,
              0.541449377329581e-8],
        "l": [0.260702058647537e10, -.188277213604704e15, 0.554923870289667e19,
              -.758966946387758e23, .413865186848908e27, -.81503800073806e12,
              -.381458260489955e33, -.123239564600519e-1, 0.226095631437174e8,
              -.49501780950672e12, 0.529482996422863e16, -0.444359478746295e23,
              .521635864527315e35, -0.487095672740742e55, -0.714430209937547e6,
              0.127868634615495, -0.100752127917598e2, 0.777451437960990e7,
              -.108105480796471e25, -.357578581169659e-5, -0.212857169423484e1,
              0.270706111085238e30, -0.695953622348829e33, 0.110609027472280,
              0.721559163361354e2, -0.306367307532219e15, 0.265839618885530e-4,
              0.253392392889754e-1, -0.214443041836579e3, 0.937846601489667,
              0.223184043101700e1, 0.338401222509191e2, 0.494237237179718e21,
              -0.198068404154428, -0.141415349881140e31, -0.993862421613651e2,
              0.125070534142731e3, -0.996473529004439e3, 0.473137909872765e5,
              0.116662121219322e33, -0.315874976271533e16,
              -0.445703369196945e33, 0.642794932373694e33],
        "m": [0.811384363481847, -0.568199310990094e4, -0.178657198172556e11,
              0.795537657613427e32, -0.814568209346872e5, -0.659774567602874e8,
              -.152861148659302e11, -0.560165667510446e12, 0.458384828593949e6,
              -0.385754000383848e14, 0.453735800004273e8, 0.939454935735563e12,
              .266572856432938e28, -0.547578313899097e10, 0.200725701112386e15,
              0.185007245563239e13, 0.185135446828337e9, -0.170451090076385e12,
              0.157890366037614e15, -0.202530509748774e16, 0.36819392618357e60,
              0.170215539458936e18, 0.639234909918741e42, -.821698160721956e15,
              -.795260241872306e24, 0.23341586947851e18, -0.600079934586803e23,
              0.594584382273384e25, 0.189461279349492e40, -.810093428842645e46,
              0.188813911076809e22, 0.111052244098768e36, 0.291133958602503e46,
              -.329421923951460e22, -.137570282536696e26, 0.181508996303902e28,
              -.346865122768353e30, -.21196114877426e38, -0.128617899887675e49,
              0.479817895699239e65],
        "n": [.280967799943151e-38, .614869006573609e-30, .582238667048942e-27,
              .390628369238462e-22, .821445758255119e-20, .402137961842776e-14,
              .651718171878301e-12, -.211773355803058e-7, 0.264953354380072e-2,
              -.135031446451331e-31, -.607246643970893e-23,
              -.402352115234494e-18, -.744938506925544e-16,
              .189917206526237e-12, .364975183508473e-5, .177274872361946e-25,
              -.334952758812999e-18, -.421537726098389e-8,
              -.391048167929649e-1, .541276911564176e-13, .705412100773699e-11,
              .258585887897486e-8, -.493111362030162e-10, -.158649699894543e-5,
              -0.525037427886100, 0.220019901729615e-2, -0.643064132636925e-2,
              0.629154149015048e2, 0.135147318617061e3, 0.240560808321713e-6,
              -.890763306701305e-3, -0.440209599407714e4, -0.302807107747776e3,
              0.159158748314599e4, 0.232534272709876e6, -0.792681207132600e6,
              -.869871364662769e11, .354542769185671e12, 0.400849240129329e15],
        "o": [.128746023979718e-34, -.735234770382342e-11, .28907869214915e-2,
              0.244482731907223, 0.141733492030985e-23, -0.354533853059476e-28,
              -.594539202901431e-17, -.585188401782779e-8, .201377325411803e-5,
              0.138647388209306e1, -0.173959365084772e-4, 0.137680878349369e-2,
              .814897605805513e-14, .425596631351839e-25,
              -.387449113787755e-17, .13981474793024e-12, -.171849638951521e-2,
              0.641890529513296e-21, .118960578072018e-10,
              -.155282762571611e-17, .233907907347507e-7,
              -.174093247766213e-12, .377682649089149e-8,
              -.516720236575302e-10],
        "p": [-0.982825342010366e-4, 0.105145700850612e1, 0.116033094095084e3,
              0.324664750281543e4, -0.123592348610137e4, -0.561403450013495e-1,
              0.856677401640869e-7, 0.236313425393924e3, 0.972503292350109e-2,
              -.103001994531927e1, -0.149653706199162e-8, -.215743778861592e-4,
              -0.834452198291445e1, 0.586602660564988, 0.343480022104968e-25,
              .816256095947021e-5, .294985697916798e-2, 0.711730466276584e-16,
              0.400954763806941e-9, 0.107766027032853e2, -0.409449599138182e-6,
              -.729121307758902e-5, 0.677107970938909e-8, 0.602745973022975e-7,
              -.382323011855257e-10, .179946628317437e-2,
              -.345042834640005e-3],
        "q": [-0.820433843259950e5, 0.473271518461586e11, -.805950021005413e-1,
              0.328600025435980e2, -0.35661702998249e4, -0.172985781433335e10,
              0.351769232729192e8, -0.775489259985144e6, 0.710346691966018e-4,
              0.993499883820274e5, -0.642094171904570, -0.612842816820083e4,
              .232808472983776e3, -0.142808220416837e-4, -0.643596060678456e-2,
              -0.428577227475614e1, 0.225689939161918e4, 0.100355651721510e-2,
              0.333491455143516, 0.109697576888873e1, 0.961917379376452,
              -0.838165632204598e-1, 0.247795908411492e1, -.319114969006533e4],
        "r": [.144165955660863e-2, -.701438599628258e13, -.830946716459219e-16,
              0.261975135368109, 0.393097214706245e3, -0.104334030654021e5,
              0.490112654154211e9, -0.147104222772069e-3, 0.103602748043408e1,
              0.305308890065089e1, -0.399745276971264e7, 0.569233719593750e-11,
              -.464923504407778e-1, -.535400396512906e-17,
              .399988795693162e-12, -.536479560201811e-6, .159536722411202e-1,
              .270303248860217e-14, .244247453858506e-7, -0.983430636716454e-5,
              0.663513144224454e-1, -0.993456957845006e1, 0.546491323528491e3,
              -0.143365406393758e5, 0.150764974125511e6, -.337209709340105e-9,
              0.377501980025469e-8],
        "s": [-0.532466612140254e23, .100415480000824e32, -.191540001821367e30,
              0.105618377808847e17, 0.202281884477061e59, 0.884585472596134e8,
              0.166540181638363e23, -0.313563197669111e6, -.185662327545324e54,
              -.624942093918942e-1, -0.50416072413259e10, 0.187514491833092e5,
              0.121399979993217e-2, 0.188317043049455e1, -0.167073503962060e4,
              0.965961650599775, 0.294885696802488e1, -0.653915627346115e5,
              0.604012200163444e50, -0.198339358557937, -0.175984090163501e58,
              0.356314881403987e1, -0.575991255144384e3, 0.456213415338071e5,
              -.109174044987829e8, 0.437796099975134e34, -0.616552611135792e46,
              0.193568768917797e10, 0.950898170425042e54],
        "t": [0.155287249586268e1, 0.664235115009031e1, -0.289366236727210e4,
              -0.385923202309848e13, -.291002915783761e1, -.829088246858083e12,
              0.176814899675218e1, -0.534686695713469e9, 0.160464608687834e18,
              0.196435366560186e6, 0.156637427541729e13, -0.178154560260006e1,
              -0.229746237623692e16, 0.385659001648006e8, 0.110554446790543e10,
              -.677073830687349e14, -.327910592086523e31, -.341552040860644e51,
              -.527251339709047e21, .245375640937055e24, -0.168776617209269e27,
              .358958955867578e29, -0.656475280339411e36, 0.355286045512301e39,
              .569021454413270e58, -.700584546433113e48, -0.705772623326374e65,
              0.166861176200148e53, -.300475129680486e61, -.668481295196808e51,
              .428432338620678e69, -.444227367758304e72, -.281396013562745e77],
        "u": [0.122088349258355e18, 0.104216468608488e10, -.882666931564652e16,
              .259929510849499e20, 0.222612779142211e15, -0.878473585050085e18,
              -0.314432577551552e22, -.216934916996285e13, .159079648196849e21,
              -.339567617303423e3, 0.884387651337836e13, -0.843405926846418e21,
              0.114178193518022e2, -0.122708229235641e-3, -0.106201671767107e3,
              .903443213959313e25, -0.693996270370852e28, 0.648916718965575e-8,
              0.718957567127851e4, 0.105581745346187e-2, -0.651903203602581e15,
              -0.160116813274676e25, -0.510254294237837e-8, -0.152355388953402,
              0.677143292290144e12, 0.276378438378930e15, 0.116862983141686e-1,
              -.301426947980171e14, 0.169719813884840e-7, 0.104674840020929e27,
              -0.10801690456014e5, -0.990623601934295e-12, 0.536116483602738e7,
              .226145963747881e22, -0.488731565776210e-9, 0.151001548880670e-4,
              -0.227700464643920e5, -0.781754507698846e28],
        "v": [-.415652812061591e-54, .177441742924043e-60,
              -.357078668203377e-54, 0.359252213604114e-25,
              -0.259123736380269e2, 0.594619766193460e5, -0.624184007103158e11,
              0.313080299915944e17, .105006446192036e-8, -0.192824336984852e-5,
              0.654144373749937e6, 0.513117462865044e13, -.697595750347391e19,
              -.103977184454767e29, .119563135540666e-47,
              -.436677034051655e-41, .926990036530639e-29, .587793105620748e21,
              .280375725094731e-17, -0.192359972440634e23, .742705723302738e27,
              -0.517429682450605e2, 0.820612048645469e7, -0.188214882341448e-8,
              .184587261114837e-1, -0.135830407782663e-5, -.723681885626348e17,
              -.223449194054124e27, -.111526741826431e-34,
              .276032601145151e-28, 0.134856491567853e15, 0.652440293345860e-9,
              0.510655119774360e17, -.468138358908732e32, -.760667491183279e16,
              -.417247986986821e-18, 0.312545677756104e14,
              -.100375333864186e15, .247761392329058e27],
        "w": [-.586219133817016e-7, -.894460355005526e11, .531168037519774e-30,
              0.109892402329239, -0.575368389425212e-1, 0.228276853990249e5,
              -.158548609655002e19, .329865748576503e-27,
              -.634987981190669e-24, 0.615762068640611e-8, -.961109240985747e8,
              -.406274286652625e-44, -0.471103725498077e-12, 0.725937724828145,
              .187768525763682e-38, -.103308436323771e4, -0.662552816342168e-1,
              0.579514041765710e3, .237416732616644e-26, .271700235739893e-14,
              -0.9078862134836e2, -0.171242509570207e-36, 0.156792067854621e3,
              0.923261357901470, -0.597865988422577e1, 0.321988767636389e7,
              -.399441390042203e-29, .493429086046981e-7, .812036983370565e-19,
              -.207610284654137e-11, -.340821291419719e-6,
              .542000573372233e-17, -.856711586510214e-12,
              0.266170454405981e-13, 0.858133791857099e-5],
        "x": [.377373741298151e19, -.507100883722913e13, -0.10336322559886e16,
              .184790814320773e-5, -.924729378390945e-3, -0.425999562292738e24,
              -.462307771873973e-12, .107319065855767e22, 0.648662492280682e11,
              0.244200600688281e1, -0.851535733484258e10, 0.169894481433592e22,
              0.215780222509020e-26, -0.320850551367334, -0.382642448458610e17,
              -.275386077674421e-28, -.563199253391666e6, -.326068646279314e21,
              0.397949001553184e14, 0.100824008584757e-6, 0.162234569738433e5,
              -0.432355225319745e11, -.59287424559861e12, 0.133061647281106e1,
              0.157338197797544e7, 0.258189614270853e14, 0.262413209706358e25,
              -.920011937431142e-1, 0.220213765905426e-2, -0.110433759109547e2,
              0.847004870612087e7, -0.592910695762536e9, -0.183027173269660e-4,
              0.181339603516302, -0.119228759669889e4, 0.430867658061468e7],
        "y": [-0.525597995024633e-9, 0.583441305228407e4, -.134778968457925e17,
              .118973500934212e26, -0.159096490904708e27, -.315839902302021e-6,
              0.496212197158239e3, 0.327777227273171e19, -0.527114657850696e22,
              .210017506281863e-16, 0.705106224399834e21, -.266713136106469e31,
              -0.145370512554562e-7, 0.149333917053130e28, -.149795620287641e8,
              -.3818819062711e16, 0.724660165585797e-4, -0.937808169550193e14,
              0.514411468376383e10, -0.828198594040141e5],
        "z": [0.24400789229065e-10, -0.463057430331242e7, 0.728803274777712e10,
              .327776302858856e16, -.110598170118409e10, -0.323899915729957e13,
              .923814007023245e16, 0.842250080413712e-12, 0.663221436245506e12,
              -.167170186672139e15, .253749358701391e4, -0.819731559610523e-20,
              0.328380587890663e12, -0.625004791171543e8, 0.803197957462023e21,
              -.204397011338353e-10, -.378391047055938e4, 0.97287654593862e-2,
              0.154355721681459e2, -0.373962862928643e4, -0.682859011374572e11,
              -0.248488015614543e-3, 0.394536049497068e7]}

    I = I[x]
    J = J[x]
    n = n[x]
    v_, P_, T_, a, b, c, d, e = par[x]

    Pr = P/P_
    Tr = T/T_
    suma = 0
    if x == "n":
        for i, j, ni in zip(I, J, n):
            suma += ni * (Pr-a)**i * (Tr-b)**j
        return v_*exp(suma)
    else:
        for i, j, ni in zip(I, J, n):
            suma += ni * (Pr-a)**(c*i) * (Tr-b)**(j*d)
        return v_*suma**e

Response: Backward equation for region 3x v = f P x


Instruction:
Implement a Python 3 function for
returning the region definition for input T and P.

Response:
def _Bound_TP(T, P):
    """Region definition for input T and P

    Parameters
    ----------
    T : float
        Temperature, [K]
    P : float
        Pressure, [MPa]

    Returns
    -------
    region : float
        IAPWS-97 region code

    References
    ----------
    Wagner, W; Kretzschmar, H-J: International Steam Tables: Properties of
    Water and Steam Based on the Industrial Formulation IAPWS-IF97; Springer,
    2008; doi: 10.1007/978-3-540-74234-0. Fig. 2.3
    """
    region = None
    if 1073.15 < T <= 2273.15 and Pmin <= P <= 50:
        region = 5
    elif Pmin <= P <= Ps_623:
        Tsat = _TSat_P(P)
        if 273.15 <= T <= Tsat:
            region = 1
        elif Tsat < T <= 1073.15:
            region = 2
    elif Ps_623 < P <= 100:
        T_b23 = _t_P(P)
        if 273.15 <= T <= 623.15:
            region = 1
        elif 623.15 < T < T_b23:
            region = 3
        elif T_b23 <= T <= 1073.15:
            region = 2
    return region


Instruction:
Given the following Python 3 function, write the documentation
def prop0(T, P):
    if T <= 1073.15:
        Tr = 540/T
        Pr = P/1.
        go, gop, gopp, got, gott, gopt = Region2_cp0(Tr, Pr)
    else:
        Tr = 1000/T
        Pr = P/1.
        go, gop, gopp, got, gott, gopt = Region5_cp0(Tr, Pr)

    prop0 = {}
    prop0["v"] = Pr*gop*R*T/P/1000
    prop0["h"] = Tr*got*R*T
    prop0["s"] = R*(Tr*got-go)
    prop0["cp"] = -R*Tr**2*gott
    prop0["cv"] = R*(-Tr**2*gott-1)

    prop0["w"] = (R*T*1000/(1+1/Tr**2/gott))**0.5
    prop0["alfav"] = 1/T
    prop0["xkappa"] = 1/P
    return prop0

Response: Ideal gas properties of a single resource.


Instruction:
Write a Python 3 function that can
check if the class is calculable by its kwargs

Response:
def calculable(self):
        """Check if class is calculable by its kwargs"""
        self._thermo = ""
        if self.kwargs["T"] and self.kwargs["P"]:
            self._thermo = "TP"
        elif self.kwargs["P"] and self.kwargs["h"] is not None:
            self._thermo = "Ph"
        elif self.kwargs["P"] and self.kwargs["s"] is not None:
            self._thermo = "Ps"
        # TODO: Add other pairs definitions options
        # elif self.kwargs["P"] and self.kwargs["v"]:
            # self._thermo = "Pv"
        # elif self.kwargs["T"] and self.kwargs["s"] is not None:
            # self._thermo = "Ts"
        elif self.kwargs["h"] is not None and self.kwargs["s"] is not None:
            self._thermo = "hs"
        elif self.kwargs["T"] and self.kwargs["x"] is not None:
            self._thermo = "Tx"
        elif self.kwargs["P"] and self.kwargs["x"] is not None:
            self._thermo = "Px"
        return self._thermo


Instruction:
Can you generate the documentation for the following Python 3 function
def derivative(self, z, x, y, fase):
        return deriv_G(self, z, x, y, fase)

Response:
Wrapper for derivative for custom derived properties
        where x y z can be P T v u h s g a


Instruction:
Can you generate the documentation for the following Python 3 function
def Ttr(x):
    if 0 <= x <= 0.33367:
        Ttr = 273.16*(1-0.3439823*x-1.3274271*x**2-274.973*x**3)
    elif 0.33367 < x <= 0.58396:
        Ttr = 193.549*(1-4.987368*(x-0.5)**2)
    elif 0.58396 < x <= 0.81473:
        Ttr = 194.38*(1-4.886151*(x-2/3)**2+10.37298*(x-2/3)**3)
    elif 0.81473 < x <= 1:
        Ttr = 195.495*(1-0.323998*(1-x)-15.87560*(1-x)**4)
    else:
        raise NotImplementedError("Incoming out of bound")
    return Ttr

Response: Equation for the triple point of ammonia - water mixture.


Instruction:
Can you tell what is the following Python 3 function doing
def _prop(self, rho, T, x):
        # FIXME: The values are good, bad difer by 1%, a error I can find
        # In Pressure happen and only use fird

        M = (1-x)*IAPWS95.M + x*NH3.M
        R = 8.314471/M

        phio = self._phi0(rho, T, x)
        fio = phio["fio"]
        tau0 = phio["tau"]
        fiot = phio["fiot"]
        fiott = phio["fiott"]

        phir = self._phir(rho, T, x)
        fir = phir["fir"]
        tau = phir["tau"]
        delta = phir["delta"]
        firt = phir["firt"]
        firtt = phir["firtt"]
        fird = phir["fird"]
        firdd = phir["firdd"]
        firdt = phir["firdt"]
        F = phir["F"]

        prop = {}
        Z = 1 + delta*fird
        prop["M"] = M
        prop["P"] = Z*R*T*rho/1000
        prop["u"] = R*T*(tau0*fiot + tau*firt)
        prop["s"] = R*(tau0*fiot + tau*firt - fio - fir)
        prop["h"] = R*T*(1+delta*fird+tau0*fiot+tau*firt)
        prop["g"] = prop["h"]-T*prop["s"]
        prop["a"] = prop["u"]-T*prop["s"]
        cvR = -tau0**2*fiott - tau**2*firtt
        prop["cv"] = R*cvR
        prop["cp"] = R*(cvR+(1+delta*fird-delta*tau*firdt)**2 /
                        (1+2*delta*fird+delta**2*firdd))
        prop["w"] = (R*T*1000*(1+2*delta*fird+delta**2*firdd +
                               (1+delta*fird-delta*tau*firdt)**2 / cvR))**0.5
        prop["fugH2O"] = Z*exp(fir+delta*fird-x*F)
        prop["fugNH3"] = Z*exp(fir+delta*fird+(1-x)*F)
        return prop

Response: Returns a dict containing the properties of the thermodynamic properties of the ammonia - water mixture with the given temperature rho and Mole fraction x.


Instruction:
How would you explain what the following Python 3 function does
def _phi0(self, rho, T, x):
        # Define reducing parameters for mixture model
        M = (1-x)*IAPWS95.M + x*NH3.M
        tau = 500/T
        delta = rho/15/M

        # Table 2
        Fi0 = {
            "log_water": 3.006320,
            "ao_water": [-7.720435, 8.649358],
            "pow_water": [0, 1],
            "ao_exp": [0.012436, 0.97315, 1.279500, 0.969560, 0.248730],
            "titao": [1.666, 4.578, 10.018, 11.964, 35.600],
            "log_nh3": -1.0,
            "ao_nh3": [-16.444285, 4.036946, 10.69955, -1.775436, 0.82374034],
            "pow_nh3": [0, 1, 1/3, -3/2, -7/4]}

        fiod = 1/delta
        fiodd = -1/delta**2
        fiodt = 0
        fiow = fiotw = fiottw = 0
        fioa = fiota = fiotta = 0

        # Water section
        if x < 1:
            fiow = Fi0["log_water"]*log(tau) + log(1-x)
            fiotw = Fi0["log_water"]/tau
            fiottw = -Fi0["log_water"]/tau**2
            for n, t in zip(Fi0["ao_water"], Fi0["pow_water"]):
                fiow += n*tau**t
                if t != 0:
                    fiotw += t*n*tau**(t-1)
                if t not in [0, 1]:
                    fiottw += n*t*(t-1)*tau**(t-2)
            for n, t in zip(Fi0["ao_exp"], Fi0["titao"]):
                fiow += n*log(1-exp(-tau*t))
                fiotw += n*t*((1-exp(-t*tau))**-1-1)
                fiottw -= n*t**2*exp(-t*tau)*(1-exp(-t*tau))**-2

        # ammonia section
        if x > 0:
            fioa = Fi0["log_nh3"]*log(tau) + log(x)
            fiota = Fi0["log_nh3"]/tau
            fiotta = -Fi0["log_nh3"]/tau**2
            for n, t in zip(Fi0["ao_nh3"], Fi0["pow_nh3"]):
                fioa += n*tau**t
                if t != 0:
                    fiota += t*n*tau**(t-1)
                if t not in [0, 1]:
                    fiotta += n*t*(t-1)*tau**(t-2)

        prop = {}
        prop["tau"] = tau
        prop["delta"] = delta
        prop["fio"] = log(delta) + (1-x)*fiow + x*fioa
        prop["fiot"] = (1-x)*fiotw + x*fiota
        prop["fiott"] = (1-x)*fiottw + x*fiotta
        prop["fiod"] = fiod
        prop["fiodd"] = fiodd
        prop["fiodt"] = fiodt
        return prop

Response: This function is used to calculate the phi0 of the base class.


Instruction:
Can you create a Python 3 function that
calls a custom preprocessing method first then rename grid attrs. This wrapper is needed to generate a single function to pass to the ``preprocesss`` of xr.open_mfdataset. It makes sure that the user-specified preprocess function is called on the loaded Dataset before aospy's is applied. An example for why this might be needed is output from the WRF model; one needs to add a CF-compliant units attribute to the time coordinate of all input files, because it is not present by default. Parameters ---------- func : function An arbitrary function to call before calling ``grid_attrs_to_aospy_names`` in ``_load_data_from_disk``. Must take an xr.Dataset as an argument as well as ``**kwargs``. grid_attrs : dict (optional) Overriding dictionary of grid attributes mapping aospy internal names to names of grid attributes used in a particular model. Returns ------- function A function that calls the provided function ``func`` on the Dataset before calling ``grid_attrs_to_aospy_names``; this is meant to be passed as a ``preprocess`` argument to ``xr.open_mfdataset``.

Response:
def _preprocess_and_rename_grid_attrs(func, grid_attrs=None, **kwargs):
    """Call a custom preprocessing method first then rename grid attrs.

    This wrapper is needed to generate a single function to pass to the
    ``preprocesss`` of xr.open_mfdataset.  It makes sure that the
    user-specified preprocess function is called on the loaded Dataset before
    aospy's is applied.  An example for why this might be needed is output from
    the WRF model; one needs to add a CF-compliant units attribute to the time
    coordinate of all input files, because it is not present by default.

    Parameters
    ----------
    func : function
       An arbitrary function to call before calling
       ``grid_attrs_to_aospy_names`` in ``_load_data_from_disk``.  Must take
       an xr.Dataset as an argument as well as ``**kwargs``.
    grid_attrs : dict (optional)
        Overriding dictionary of grid attributes mapping aospy internal
        names to names of grid attributes used in a particular model.

    Returns
    -------
    function
        A function that calls the provided function ``func`` on the Dataset
        before calling ``grid_attrs_to_aospy_names``; this is meant to be
        passed as a ``preprocess`` argument to ``xr.open_mfdataset``.
    """

    def func_wrapper(ds):
        return grid_attrs_to_aospy_names(func(ds, **kwargs), grid_attrs)
    return func_wrapper


Instruction:
Can you tell what is the following Python 3 function doing
def grid_attrs_to_aospy_names(data, grid_attrs=None):
    if grid_attrs is None:
        grid_attrs = {}

    # Override GRID_ATTRS with entries in grid_attrs
    attrs = GRID_ATTRS.copy()
    for k, v in grid_attrs.items():
        if k not in attrs:
            raise ValueError(
                'Unrecognized internal name, {!r}, specified for a custom '
                'grid attribute name.  See the full list of valid internal '
                'names below:\n\n{}'.format(k, list(GRID_ATTRS.keys())))
        attrs[k] = (v, )

    dims_and_vars = set(data.variables).union(set(data.dims))
    for name_int, names_ext in attrs.items():
        data_coord_name = set(names_ext).intersection(dims_and_vars)
        if data_coord_name:
            data = data.rename({data_coord_name.pop(): name_int})
    return set_grid_attrs_as_coords(data)

Response: Rename grid attributes to be consistent with aospy internal names.


Instruction:
Can you create a Python 3 function that
sets available grid attributes as coordinates in a given Dataset.

Response:
def set_grid_attrs_as_coords(ds):
    """Set available grid attributes as coordinates in a given Dataset.

    Grid attributes are assumed to have their internal aospy names. Grid
    attributes are set as coordinates, such that they are carried by all
    selected DataArrays with overlapping index dimensions.

    Parameters
    ----------
    ds : Dataset
        Input data

    Returns
    -------
    Dataset
        Dataset with grid attributes set as coordinates
    """
    grid_attrs_in_ds = set(GRID_ATTRS.keys()).intersection(
        set(ds.coords) | set(ds.data_vars))
    ds = ds.set_coords(grid_attrs_in_ds)
    return ds


Instruction:
Write a Python 3 function that can
cast DataArrays to np. float64 if they are of type np. float32.

Response:
def _maybe_cast_to_float64(da):
    """Cast DataArrays to np.float64 if they are of type np.float32.

    Parameters
    ----------
    da : xr.DataArray
        Input DataArray

    Returns
    -------
    DataArray
    """
    if da.dtype == np.float32:
        logging.warning('Datapoints were stored using the np.float32 datatype.'
                        'For accurate reduction operations using bottleneck, '
                        'datapoints are being cast to the np.float64 datatype.'
                        ' For more information see: https://github.com/pydata/'
                        'xarray/issues/1346')
        return da.astype(np.float64)
    else:
        return da


Instruction:
How would you explain what the following Python 3 function does
def _sel_var(ds, var, upcast_float32=True):
    for name in var.names:
        try:
            da = ds[name].rename(var.name)
            if upcast_float32:
                return _maybe_cast_to_float64(da)
            else:
                return da
        except KeyError:
            pass
    msg = '{0} not found among names: {1} in\n{2}'.format(var, var.names, ds)
    raise LookupError(msg)

Response: Select the specified variable by trying all possible alternative names.


Instruction:
Can you create a Python 3 function that
prepares time coordinate information in Dataset for use in aospy.

Response:
def _prep_time_data(ds):
    """Prepare time coordinate information in Dataset for use in aospy.

    1. If the Dataset contains a time bounds coordinate, add attributes
       representing the true beginning and end dates of the time interval used
       to construct the Dataset
    2. If the Dataset contains a time bounds coordinate, overwrite the time
       coordinate values with the averages of the time bounds at each timestep
    3. Decode the times into np.datetime64 objects for time indexing

    Parameters
    ----------
    ds : Dataset
        Pre-processed Dataset with time coordinate renamed to
        internal_names.TIME_STR

    Returns
    -------
    Dataset
        The processed Dataset
    """
    ds = times.ensure_time_as_index(ds)
    if TIME_BOUNDS_STR in ds:
        ds = times.ensure_time_avg_has_cf_metadata(ds)
        ds[TIME_STR] = times.average_time_bounds(ds)
    else:
        logging.warning("dt array not found.  Assuming equally spaced "
                        "values in time, even though this may not be "
                        "the case")
        ds = times.add_uniform_time_weights(ds)
    # Suppress enable_cftimeindex is a no-op warning; we'll keep setting it for
    # now to maintain backwards compatibility for older xarray versions.
    with warnings.catch_warnings():
        warnings.filterwarnings('ignore')
        with xr.set_options(enable_cftimeindex=True):
            ds = xr.decode_cf(ds, decode_times=True, decode_coords=False,
                              mask_and_scale=True)
    return ds


Instruction:
Write a Python 3 function for
loading a Dataset from a list or glob - string of files.

Response:
def _load_data_from_disk(file_set, preprocess_func=lambda ds: ds,
                         data_vars='minimal', coords='minimal',
                         grid_attrs=None, **kwargs):
    """Load a Dataset from a list or glob-string of files.

    Datasets from files are concatenated along time,
    and all grid attributes are renamed to their aospy internal names.

    Parameters
    ----------
    file_set : list or str
        List of paths to files or glob-string
    preprocess_func : function (optional)
        Custom function to call before applying any aospy logic
        to the loaded dataset
    data_vars : str (default 'minimal')
        Mode for concatenating data variables in call to ``xr.open_mfdataset``
    coords : str (default 'minimal')
        Mode for concatenating coordinate variables in call to
        ``xr.open_mfdataset``.
    grid_attrs : dict
        Overriding dictionary of grid attributes mapping aospy internal
        names to names of grid attributes used in a particular model.

    Returns
    -------
    Dataset
    """
    apply_preload_user_commands(file_set)
    func = _preprocess_and_rename_grid_attrs(preprocess_func, grid_attrs,
                                             **kwargs)
    return xr.open_mfdataset(file_set, preprocess=func, concat_dim=TIME_STR,
                             decode_times=False, decode_coords=False,
                             mask_and_scale=True, data_vars=data_vars,
                             coords=coords)


Instruction:
Can you tell what is the following Python 3 function doing
def _setattr_default(obj, attr, value, default):
    if value is None:
        setattr(obj, attr, default)
    else:
        setattr(obj, attr, value)

Response: Set an attribute of an object to a value or default value.


Instruction:
Can you implement a function in Python 3 that
loads a DataArray for the specified variable and time range.

Response:
def load_variable(self, var=None, start_date=None, end_date=None,
                      time_offset=None, grid_attrs=None, **DataAttrs):
        """Load a DataArray for requested variable and time range.

        Automatically renames all grid attributes to match aospy conventions.

        Parameters
        ----------
        var : Var
            aospy Var object
        start_date : datetime.datetime
            start date for interval
        end_date : datetime.datetime
            end date for interval
        time_offset : dict
            Option to add a time offset to the time coordinate to correct for
            incorrect metadata.
        grid_attrs : dict (optional)
            Overriding dictionary of grid attributes mapping aospy internal
            names to names of grid attributes used in a particular model.
        **DataAttrs
            Attributes needed to identify a unique set of files to load from

        Returns
        -------
        da : DataArray
             DataArray for the specified variable, date range, and interval in
        """
        file_set = self._generate_file_set(var=var, start_date=start_date,
                                           end_date=end_date, **DataAttrs)
        ds = _load_data_from_disk(
            file_set, self.preprocess_func, data_vars=self.data_vars,
            coords=self.coords, start_date=start_date, end_date=end_date,
            time_offset=time_offset, grid_attrs=grid_attrs, **DataAttrs
        )
        if var.def_time:
            ds = _prep_time_data(ds)
            start_date = times.maybe_convert_to_index_date_type(
                ds.indexes[TIME_STR], start_date)
            end_date = times.maybe_convert_to_index_date_type(
                ds.indexes[TIME_STR], end_date)
        ds = set_grid_attrs_as_coords(ds)
        da = _sel_var(ds, var, self.upcast_float32)
        if var.def_time:
            da = self._maybe_apply_time_shift(da, time_offset, **DataAttrs)
            return times.sel_time(da, start_date, end_date).load()
        else:
            return da.load()


Instruction:
Write a Python 3 script for
loading a DataArray for the requested variable and time range using the provided Model object.

Response:
def _load_or_get_from_model(self, var, start_date=None, end_date=None,
                                time_offset=None, model=None, **DataAttrs):
        """Load a DataArray for the requested variable and time range

        Supports both access of grid attributes either through the DataLoader
        or through an optionally-provided Model object.  Defaults to using
        the version found in the DataLoader first.
        """
        grid_attrs = None if model is None else model.grid_attrs

        try:
            return self.load_variable(
                var, start_date=start_date, end_date=end_date,
                time_offset=time_offset, grid_attrs=grid_attrs, **DataAttrs)
        except (KeyError, IOError) as e:
            if var.name not in GRID_ATTRS or model is None:
                raise e
            else:
                try:
                    return getattr(model, var.name)
                except AttributeError:
                    raise AttributeError(
                        'Grid attribute {} could not be located either '
                        'through this DataLoader or in the provided Model '
                        'object: {}.'.format(var, model))


Instruction:
Write a Python 3 function that can
compute a variable recursively loading data where needed.

Response:
def recursively_compute_variable(self, var, start_date=None, end_date=None,
                                     time_offset=None, model=None,
                                     **DataAttrs):
        """Compute a variable recursively, loading data where needed.

        An obvious requirement here is that the variable must eventually be
        able to be expressed in terms of model-native quantities; otherwise the
        recursion will never stop.

        Parameters
        ----------
        var : Var
            aospy Var object
        start_date : datetime.datetime
            start date for interval
        end_date : datetime.datetime
            end date for interval
        time_offset : dict
            Option to add a time offset to the time coordinate to correct for
            incorrect metadata.
        model : Model
            aospy Model object (optional)
        **DataAttrs
            Attributes needed to identify a unique set of files to load from

        Returns
        -------
        da : DataArray
             DataArray for the specified variable, date range, and interval in
        """
        if var.variables is None:
            return self._load_or_get_from_model(
                var, start_date, end_date, time_offset, model, **DataAttrs)
        else:
            data = [self.recursively_compute_variable(
                v, start_date, end_date, time_offset, model, **DataAttrs)
                    for v in var.variables]
            return var.func(*data).rename(var.name)


Instruction:
Can you generate the documentation for the following Python 3 function
def _maybe_apply_time_shift(da, time_offset=None, **DataAttrs):
        if time_offset is not None:
            time = times.apply_time_offset(da[TIME_STR], **time_offset)
            da[TIME_STR] = time
        return da

Response: Apply specified time shift to DataArray


Instruction:
Can you generate a brief explanation for the following Python 3 code
def _generate_file_set(self, var=None, start_date=None, end_date=None,
                           domain=None, intvl_in=None, dtype_in_vert=None,
                           dtype_in_time=None, intvl_out=None):
        """Returns the file_set for the given interval in."""
        try:
            return self.file_map[intvl_in]
        except KeyError:
            raise KeyError('File set does not exist for the specified'
                           ' intvl_in {0}'.format(intvl_in))

Response: Returns the file_set for the given interval in.


Instruction:
Explain what the following Python 3 code does
def _maybe_apply_time_shift(da, time_offset=None, **DataAttrs):
        if time_offset is not None:
            time = times.apply_time_offset(da[TIME_STR], **time_offset)
            da[TIME_STR] = time
        else:
            if DataAttrs['dtype_in_time'] == 'inst':
                if DataAttrs['intvl_in'].endswith('hr'):
                    offset = -1 * int(DataAttrs['intvl_in'][0])
                else:
                    offset = 0
                time = times.apply_time_offset(da[TIME_STR], hours=offset)
                da[TIME_STR] = time
        return da

Response: Apply time shift to the data.


Instruction:
Write a Python 3 function that can
convert the given data to plotting units.

Response:
def to_plot_units(self, data, dtype_vert=False):
        """Convert the given data to plotting units."""
        if dtype_vert == 'vert_av' or not dtype_vert:
            conv_factor = self.units.plot_units_conv
        elif dtype_vert == ('vert_int'):
            conv_factor = self.units.vert_int_plot_units_conv
        else:
            raise ValueError("dtype_vert value `{0}` not recognized.  Only "
                             "bool(dtype_vert) = False, 'vert_av', and "
                             "'vert_int' supported.".format(dtype_vert))
        if isinstance(data, dict):
            return {key: val*conv_factor for key, val in data.items()}
        return data*conv_factor


Instruction:
Write a Python 3 function that can
mask data array where values are outside physically valid range.

Response:
def mask_unphysical(self, data):
        """Mask data array where values are outside physically valid range."""
        if not self.valid_range:
            return data
        else:
            return np.ma.masked_outside(data, np.min(self.valid_range),
                                        np.max(self.valid_range))


Instruction:
Implement a Python 3 function for
forcing data with units either degrees or radians to be radians.

Response:
def to_radians(arr, is_delta=False):
    """Force data with units either degrees or radians to be radians."""
    # Infer the units from embedded metadata, if it's there.
    try:
        units = arr.units
    except AttributeError:
        pass
    else:
        if units.lower().startswith('degrees'):
            warn_msg = ("Conversion applied: degrees -> radians to array: "
                        "{}".format(arr))
            logging.debug(warn_msg)
            return np.deg2rad(arr)
    # Otherwise, assume degrees if the values are sufficiently large.
    threshold = 0.1*np.pi if is_delta else 4*np.pi
    if np.max(np.abs(arr)) > threshold:
        warn_msg = ("Conversion applied: degrees -> radians to array: "
                    "{}".format(arr))
        logging.debug(warn_msg)
        return np.deg2rad(arr)
    return arr


Instruction:
Given the following Python 3 function, write the documentation
def to_pascal(arr, is_dp=False):
    threshold = 400 if is_dp else 1200
    if np.max(np.abs(arr)) < threshold:
        warn_msg = "Conversion applied: hPa -> Pa to array: {}".format(arr)
        logging.debug(warn_msg)
        return arr*100.
    return arr

Response: Convert array to Pa in hPa or Pa.


Instruction:
Can you tell what is the following Python 3 function doing
def to_hpa(arr):
    if np.max(np.abs(arr)) > 1200.:
        warn_msg = "Conversion applied: Pa -> hPa to array: {}".format(arr)
        logging.debug(warn_msg)
        return arr / 100.
    return arr

Response: Convert pressure array from Pa to hPa.


Instruction:
Given the following Python 3 function, write the documentation
def replace_coord(arr, old_dim, new_dim, new_coord):
    new_arr = arr.rename({old_dim: new_dim})
    new_arr[new_dim] = new_coord
    return new_arr

Response: Replace a coordinate with new one ; old must have same shape.


Instruction:
Implement a function in Python 3 to
compute data at full pressure levels from values at half levels.

Response:
def to_pfull_from_phalf(arr, pfull_coord):
    """Compute data at full pressure levels from values at half levels."""
    phalf_top = arr.isel(**{internal_names.PHALF_STR: slice(1, None)})
    phalf_top = replace_coord(phalf_top, internal_names.PHALF_STR,
                              internal_names.PFULL_STR, pfull_coord)

    phalf_bot = arr.isel(**{internal_names.PHALF_STR: slice(None, -1)})
    phalf_bot = replace_coord(phalf_bot, internal_names.PHALF_STR,
                              internal_names.PFULL_STR, pfull_coord)
    return 0.5*(phalf_bot + phalf_top)


Instruction:
Can you tell what is the following Python 3 function doing
def to_phalf_from_pfull(arr, val_toa=0, val_sfc=0):
    phalf = np.zeros((arr.shape[0] + 1, arr.shape[1], arr.shape[2]))
    phalf[0] = val_toa
    phalf[-1] = val_sfc
    phalf[1:-1] = 0.5*(arr[:-1] + arr[1:])
    return phalf

Response: Compute data at half pressure levels from values at full levels.


Instruction:
Can you generate the documentation for the following Python 3 function
def pfull_from_ps(bk, pk, ps, pfull_coord):
    return to_pfull_from_phalf(phalf_from_ps(bk, pk, ps), pfull_coord)

Response: Compute pressure at full levels from surface pressure.


Instruction:
Given the following Python 3 function, write the documentation
def d_deta_from_phalf(arr, pfull_coord):
    d_deta = arr.diff(dim=internal_names.PHALF_STR, n=1)
    return replace_coord(d_deta, internal_names.PHALF_STR,
                         internal_names.PFULL_STR, pfull_coord)

Response: Compute pressure level thickness from half level pressures.


Instruction:
Given the following Python 3 function, write the documentation
def d_deta_from_pfull(arr):
    right = arr[{internal_names.PFULL_STR: slice(2, None, None)}].values
    left = arr[{internal_names.PFULL_STR: slice(0, -2, 1)}].values
    deriv = xr.DataArray(np.zeros(arr.shape), dims=arr.dims,
                         coords=arr.coords)
    deriv[{internal_names.PFULL_STR: slice(1, -1, 1)}] = (right - left) / 2.
    deriv[{internal_names.PFULL_STR: 0}] = (
        arr[{internal_names.PFULL_STR: 1}].values -
        arr[{internal_names.PFULL_STR: 0}].values)
    deriv[{internal_names.PFULL_STR: -1}] = (
        arr[{internal_names.PFULL_STR: -1}].values -
        arr[{internal_names.PFULL_STR: -2}].values)
    return deriv

Response: Compute the derivative of the array on full hybrid levels.


Instruction:
Given the following Python 3 function, write the documentation
def dp_from_ps(bk, pk, ps, pfull_coord):
    return d_deta_from_phalf(phalf_from_ps(bk, pk, ps), pfull_coord)

Response: Compute pressure level thickness from surface pressure


Instruction:
Given the following Python 3 function, write the documentation
def integrate(arr, ddim, dim=False, is_pressure=False):
    if is_pressure:
        dim = vert_coord_name(ddim)
    return (arr*ddim).sum(dim=dim)

Response: Integrate along the given dimension.


Instruction:
Given the following Python 3 function, write the documentation
def get_dim_name(arr, names):
    for name in names:
        # TODO: raise warning/exception when multiple names arr attrs.
        if hasattr(arr, name):
            return name
    raise AttributeError("No attributes of the object `{0}` match the "
                         "specified names of `{1}`".format(arr, names))

Response: Determine if an object has an attribute name matching a given list.


Instruction:
Can you create a Python 3 function that
gets level thickness of pressure data incorporating surface pressure.

Response:
def dp_from_p(p, ps, p_top=0., p_bot=1.1e5):
    """Get level thickness of pressure data, incorporating surface pressure.

    Level edges are defined as halfway between the levels, as well as the user-
    specified uppermost and lowermost values.  The dp of levels whose bottom
    pressure is less than the surface pressure is not changed by ps, since they
    don't intersect the surface.  If ps is in between a level's top and bottom
    pressures, then its dp becomes the pressure difference between its top and
    ps.  If ps is less than a level's top and bottom pressures, then that level
    is underground and its values are masked.

    Note that postprocessing routines (e.g. at GFDL) typically mask out data
    wherever the surface pressure is less than the level's given value, not the
    level's upper edge.  This masks out more levels than the

    """
    p_str = get_dim_name(p, (internal_names.PLEVEL_STR, 'plev'))
    p_vals = to_pascal(p.values.copy())

    # Layer edges are halfway between the given pressure levels.
    p_edges_interior = 0.5*(p_vals[:-1] + p_vals[1:])
    p_edges = np.concatenate(([p_bot], p_edges_interior, [p_top]))
    p_edge_above = p_edges[1:]
    p_edge_below = p_edges[:-1]
    dp = p_edge_below - p_edge_above
    if not all(np.sign(dp)):
        raise ValueError("dp array not all > 0 : {}".format(dp))
    # Pressure difference between ps and the upper edge of each pressure level.
    p_edge_above_xr = xr.DataArray(p_edge_above, dims=p.dims, coords=p.coords)
    dp_to_sfc = ps - p_edge_above_xr
    # Find the level adjacent to the masked, under-ground levels.
    change = xr.DataArray(np.zeros(dp_to_sfc.shape), dims=dp_to_sfc.dims,
                          coords=dp_to_sfc.coords)
    change[{p_str: slice(1, None)}] = np.diff(
        np.sign(ps - to_pascal(p.copy()))
    )
    dp_combined = xr.DataArray(np.where(change, dp_to_sfc, dp),
                               dims=dp_to_sfc.dims, coords=dp_to_sfc.coords)
    # Mask levels that are under ground.
    above_ground = ps > to_pascal(p.copy())
    above_ground[p_str] = p[p_str]
    dp_with_ps = dp_combined.where(above_ground)
    # Revert to original dim order.
    possible_dim_orders = [
        (internal_names.TIME_STR, p_str, internal_names.LAT_STR,
         internal_names.LON_STR),
        (internal_names.TIME_STR, p_str, internal_names.LAT_STR),
        (internal_names.TIME_STR, p_str, internal_names.LON_STR),
        (internal_names.TIME_STR, p_str),
        (p_str, internal_names.LAT_STR, internal_names.LON_STR),
        (p_str, internal_names.LAT_STR),
        (p_str, internal_names.LON_STR),
        (p_str,),
    ]
    for dim_order in possible_dim_orders:
        try:
            return dp_with_ps.transpose(*dim_order)
        except ValueError:
            logging.debug("Failed transpose to dims: {}".format(dim_order))
    else:
        logging.debug("No transpose was successful.")
        return dp_with_ps


Instruction:
Write a Python 3 script for
calculating the thickness of a single pressure level.

Response:
def level_thickness(p, p_top=0., p_bot=1.01325e5):
    """
    Calculates the thickness, in Pa, of each pressure level.

    Assumes that the pressure values given are at the center of that model
    level, except for the lowest value (typically 1000 hPa), which is the
    bottom boundary. The uppermost level extends to 0 hPa.

    Unlike `dp_from_p`, this does not incorporate the surface pressure.

    """
    p_vals = to_pascal(p.values.copy())
    dp_vals = np.empty_like(p_vals)
    # Bottom level extends from p[0] to halfway betwen p[0] and p[1].
    dp_vals[0] = p_bot - 0.5*(p_vals[0] + p_vals[1])
    # Middle levels extend from halfway between [k-1], [k] and [k], [k+1].
    dp_vals[1:-1] = 0.5*(p_vals[0:-2] - p_vals[2:])
    # Top level extends from halfway between top two levels to 0 hPa.
    dp_vals[-1] = 0.5*(p_vals[-2] + p_vals[-1]) - p_top
    dp = p.copy()
    dp.values = dp_vals
    return dp


Instruction:
How would you explain what the following Python 3 function does
def does_coord_increase_w_index(arr):
    diff = np.diff(arr)
    if not np.all(np.abs(np.sign(diff))):
        raise ValueError("Array is not monotonic: {}".format(arr))
    # Since we know its monotonic, just test the first value.
    return bool(diff[0])

Response: Determine if the array values increase with the index.


Instruction:
Given the following Python 3 function, write the documentation
def apply_time_offset(time, years=0, months=0, days=0, hours=0):
    return (pd.to_datetime(time.values) +
            pd.DateOffset(years=years, months=months, days=days, hours=hours))

Response: Apply a specified offset to the given time array.


Instruction:
How would you code a function in Python 3 to
return the average of each set of time bounds in the Dataset.

Response:
def average_time_bounds(ds):
    """Return the average of each set of time bounds in the Dataset.

    Useful for creating a new time array to replace the Dataset's native time
    array, in the case that the latter matches either the start or end bounds.
    This can cause errors in grouping (akin to an off-by-one error) if the
    timesteps span e.g. one full month each.  Note that the Dataset's times
    must not have already undergone "CF decoding", wherein they are converted
    from floats using the 'units' attribute into datetime objects.

    Parameters
    ----------
    ds : xarray.Dataset
        A Dataset containing a time bounds array with name matching
        internal_names.TIME_BOUNDS_STR.  This time bounds array must have two
        dimensions, one of which's coordinates is the Dataset's time array, and
        the other is length-2.

    Returns
    -------
    xarray.DataArray
        The mean of the start and end times of each timestep in the original
        Dataset.

    Raises
    ------
    ValueError
        If the time bounds array doesn't match the shape specified above.

    """
    bounds = ds[TIME_BOUNDS_STR]
    new_times = bounds.mean(dim=BOUNDS_STR, keep_attrs=True)
    new_times = new_times.drop(TIME_STR).rename(TIME_STR)
    new_times[TIME_STR] = new_times
    return new_times


Instruction:
Implement a Python 3 function for
copying monthly mean over each time index in that month.

Response:
def monthly_mean_at_each_ind(monthly_means, sub_monthly_timeseries):
    """Copy monthly mean over each time index in that month.

    Parameters
    ----------
    monthly_means : xarray.DataArray
        array of monthly means
    sub_monthly_timeseries : xarray.DataArray
        array of a timeseries at sub-monthly time resolution

    Returns
    -------
    xarray.DataArray with eath monthly mean value from `monthly_means` repeated
    at each time within that month from `sub_monthly_timeseries`

    See Also
    --------
    monthly_mean_ts : Create timeseries of monthly mean values
    """
    time = monthly_means[TIME_STR]
    start = time.indexes[TIME_STR][0].replace(day=1, hour=0)
    end = time.indexes[TIME_STR][-1]
    new_indices = pd.DatetimeIndex(start=start, end=end, freq='MS')
    arr_new = monthly_means.reindex(time=new_indices, method='backfill')
    return arr_new.reindex_like(sub_monthly_timeseries, method='pad')


Instruction:
Can you implement a function in Python 3 that
averages a sub - yearly time - series over each year.

Response:
def yearly_average(arr, dt):
    """Average a sub-yearly time-series over each year.

    Resulting timeseries comprises one value for each year in which the
    original array had valid data.  Accounts for (i.e. ignores) masked values
    in original data when computing the annual averages.

    Parameters
    ----------
    arr : xarray.DataArray
        The array to be averaged
    dt : xarray.DataArray
        Array of the duration of each timestep

    Returns
    -------
    xarray.DataArray
        Has the same shape and mask as the original ``arr``, except for the
        time dimension, which is truncated to one value for each year that
        ``arr`` spanned

    """
    assert_matching_time_coord(arr, dt)
    yr_str = TIME_STR + '.year'
    # Retain original data's mask.
    dt = dt.where(np.isfinite(arr))
    return ((arr*dt).groupby(yr_str).sum(TIME_STR) /
            dt.groupby(yr_str).sum(TIME_STR))


Instruction:
Explain what the following Python 3 code does
def ensure_datetime(obj):
    _VALID_TYPES = (str, datetime.datetime, cftime.datetime,
                    np.datetime64)
    if isinstance(obj, _VALID_TYPES):
        return obj
    raise TypeError("datetime-like object required.  "
                    "Type given: {}".format(type(obj)))

Response: Return the original object if it is a datetime - like object.


Instruction:
How would you implement a function in Python 3 that
converts string labels for months to integer indices.

Response:
def month_indices(months):
    """Convert string labels for months to integer indices.

    Parameters
    ----------
     months : str, int
         If int, number of the desired month, where January=1, February=2,
         etc.  If str, must match either 'ann' or some subset of
         'jfmamjjasond'.  If 'ann', use all months.  Otherwise, use the
         specified months.

    Returns
    -------
    np.ndarray of integers corresponding to desired month indices

    Raises
    ------
    TypeError : If `months` is not an int or str

    See also
    --------
    _month_conditional
    """
    if not isinstance(months, (int, str)):
        raise TypeError("`months` must be of type int or str: "
                        "type(months) == {}".format(type(months)))
    if isinstance(months, int):
        return [months]
    if months.lower() == 'ann':
        return np.arange(1, 13)
    first_letter = 'jfmamjjasond' * 2
    # Python indexing starts at 0; month indices start at 1 for January.
    count = first_letter.count(months)
    if (count == 0) or (count > 2):
        message = ("The user must provide a unique pattern of consecutive "
                   "first letters of months within '{}'. The provided "
                   "string '{}' does not comply."
                   "  For individual months use integers."
                   "".format(first_letter, months))
        raise ValueError(message)
    st_ind = first_letter.find(months.lower())
    return np.arange(st_ind, st_ind + len(months)) % 12 + 1


Instruction:
Can you generate a brief explanation for the following Python 3 code
def _month_conditional(time, months):
    if isinstance(months, (int, str)):
        months_array = month_indices(months)
    else:
        months_array = months
    cond = False
    for month in months_array:
        cond |= (time['{}.month'.format(TIME_STR)] == month)
    return cond

Response: Create a conditional statement for selecting data in a DataArray for specific months.


Instruction:
How would you explain what the following Python 3 function does
def extract_months(time, months):
    inds = _month_conditional(time, months)
    return time.sel(time=inds)

Response: Extract times within specified months of the year.


Instruction:
Write a Python 3 function that can
enforce that the time average data is present in the Dataset or DataArray and adds CF metadata attributes to the dataset.

Response:
def ensure_time_avg_has_cf_metadata(ds):
    """Add time interval length and bounds coordinates for time avg data.

    If the Dataset or DataArray contains time average data, enforce
    that there are coordinates that track the lower and upper bounds of
    the time intervals, and that there is a coordinate that tracks the
    amount of time per time average interval.

    CF conventions require that a quantity stored as time averages
    over time intervals must have time and time_bounds coordinates [1]_.
    aospy further requires AVERAGE_DT for time average data, for accurate
    time-weighted averages, which can be inferred from the CF-required
    time_bounds coordinate if needed.  This step should be done
    prior to decoding CF metadata with xarray to ensure proper
    computed timedeltas for different calendar types.

    .. [1] http://cfconventions.org/cf-conventions/v1.6.0/cf-conventions.html#_data_representative_of_cells

    Parameters
    ----------
    ds : Dataset or DataArray
        Input data

    Returns
    -------
    Dataset or DataArray
        Time average metadata attributes added if needed.
    """  # noqa: E501
    if TIME_WEIGHTS_STR not in ds:
        time_weights = ds[TIME_BOUNDS_STR].diff(BOUNDS_STR)
        time_weights = time_weights.rename(TIME_WEIGHTS_STR).squeeze()
        if BOUNDS_STR in time_weights.coords:
            time_weights = time_weights.drop(BOUNDS_STR)
        ds[TIME_WEIGHTS_STR] = time_weights

    raw_start_date = ds[TIME_BOUNDS_STR].isel(**{TIME_STR: 0, BOUNDS_STR: 0})
    ds[RAW_START_DATE_STR] = raw_start_date.reset_coords(drop=True)
    raw_end_date = ds[TIME_BOUNDS_STR].isel(**{TIME_STR: -1, BOUNDS_STR: 1})
    ds[RAW_END_DATE_STR] = raw_end_date.reset_coords(drop=True)

    for coord in [TIME_BOUNDS_STR, RAW_START_DATE_STR, RAW_END_DATE_STR]:
        ds[coord].attrs['units'] = ds[TIME_STR].attrs['units']
        if 'calendar' in ds[TIME_STR].attrs:
            ds[coord].attrs['calendar'] = ds[TIME_STR].attrs['calendar']

    unit_interval = ds[TIME_STR].attrs['units'].split('since')[0].strip()
    ds[TIME_WEIGHTS_STR].attrs['units'] = unit_interval
    return ds


Instruction:
Can you write a function in Python 3 where it
appends uniform time weights to a Dataset.

Response:
def add_uniform_time_weights(ds):
    """Append uniform time weights to a Dataset.

    All DataArrays with a time coordinate require a time weights coordinate.
    For Datasets read in without a time bounds coordinate or explicit
    time weights built in, aospy adds uniform time weights at each point
    in the time coordinate.

    Parameters
    ----------
    ds : Dataset
        Input data

    Returns
    -------
    Dataset
    """
    time = ds[TIME_STR]
    unit_interval = time.attrs['units'].split('since')[0].strip()
    time_weights = xr.ones_like(time)
    time_weights.attrs['units'] = unit_interval
    del time_weights.attrs['calendar']
    ds[TIME_WEIGHTS_STR] = time_weights
    return ds


Instruction:
Write a Python 3 script to
check to make sure that data exists for the given time range.

Response:
def _assert_has_data_for_time(da, start_date, end_date):
    """Check to make sure data is in Dataset for the given time range.

    Parameters
    ----------
    da : DataArray
         DataArray with a time variable
    start_date : datetime-like object or str
         start date
    end_date : datetime-like object or str
         end date

    Raises
    ------
    AssertionError
         If the time range is not within the time range of the DataArray

    """
    if isinstance(start_date, str) and isinstance(end_date, str):
        logging.warning(
            'When using strings to specify start and end dates, the check '
            'to determine if data exists for the full extent of the desired '
            'interval is not implemented.  Therefore it is possible that '
            'you are doing a calculation for a lesser interval than you '
            'specified.  If you would like this check to occur, use explicit '
            'datetime-like objects for bounds instead.')
        return

    if RAW_START_DATE_STR in da.coords:
        with warnings.catch_warnings(record=True):
            da_start = da[RAW_START_DATE_STR].values
            da_end = da[RAW_END_DATE_STR].values
    else:
        times = da.time.isel(**{TIME_STR: [0, -1]})
        da_start, da_end = times.values

    message = ('Data does not exist for requested time range: {0} to {1};'
               ' found data from time range: {2} to {3}.')
    # Add tolerance of one second, due to precision of cftime.datetimes
    tol = datetime.timedelta(seconds=1)
    if isinstance(da_start, np.datetime64):
        tol = np.timedelta64(tol, 'ns')
    range_exists = ((da_start - tol) <= start_date and
                    (da_end + tol) >= end_date)
    assert (range_exists), message.format(start_date, end_date,
                                          da_start, da_end)


Instruction:
How would you explain what the following Python 3 function does
def sel_time(da, start_date, end_date):
    _assert_has_data_for_time(da, start_date, end_date)
    da[SUBSET_START_DATE_STR] = xr.DataArray(start_date)
    da[SUBSET_END_DATE_STR] = xr.DataArray(end_date)
    return da.sel(**{TIME_STR: slice(start_date, end_date)})

Response: Subset a DataArray or Dataset for a given date range.


Instruction:
Write a Python 3 function for
checking to see if two DataArrays have the same time coordinate.

Response:
def assert_matching_time_coord(arr1, arr2):
    """Check to see if two DataArrays have the same time coordinate.

    Parameters
    ----------
    arr1 : DataArray or Dataset
        First DataArray or Dataset
    arr2 : DataArray or Dataset
        Second DataArray or Dataset

    Raises
    ------
    ValueError
        If the time coordinates are not identical between the two Datasets
    """
    message = ('Time weights not indexed by the same time coordinate as'
               ' computed data.  This will lead to an improperly computed'
               ' time weighted average.  Exiting.\n'
               'arr1: {}\narr2: {}')
    if not (arr1[TIME_STR].identical(arr2[TIME_STR])):
        raise ValueError(message.format(arr1[TIME_STR], arr2[TIME_STR]))


Instruction:
Can you tell what is the following Python 3 function doing
def ensure_time_as_index(ds):
    time_indexed_coords = {TIME_WEIGHTS_STR, TIME_BOUNDS_STR}
    time_indexed_vars = set(ds.data_vars).union(time_indexed_coords)
    time_indexed_vars = time_indexed_vars.intersection(ds.variables)
    variables_to_replace = {}
    for name in time_indexed_vars:
        if TIME_STR not in ds[name].indexes:
            da = ds[name]
            if TIME_STR not in da.dims:
                da = ds[name].expand_dims(TIME_STR)
            da = da.assign_coords(**{TIME_STR: ds[TIME_STR]})
            variables_to_replace[name] = da
    return ds.assign(**variables_to_replace)

Response: Ensures that time is an indexed coordinate on relevant quantities.


Instruction:
How would you code a function in Python 3 to
give a datetime - like object or string infer the year.

Response:
def infer_year(date):
    """Given a datetime-like object or string infer the year.

    Parameters
    ----------
    date : datetime-like object or str
        Input date

    Returns
    -------
    int

    Examples
    --------
    >>> infer_year('2000')
    2000
    >>> infer_year('2000-01')
    2000
    >>> infer_year('2000-01-31')
    2000
    >>> infer_year(datetime.datetime(2000, 1, 1))
    2000
    >>> infer_year(np.datetime64('2000-01-01'))
    2000
    >>> infer_year(DatetimeNoLeap(2000, 1, 1))
    2000
    >>>
    """
    if isinstance(date, str):
        # Look for a string that begins with four numbers; the first four
        # numbers found are the year.
        pattern = r'(?P<year>\d{4})'
        result = re.match(pattern, date)
        if result:
            return int(result.groupdict()['year'])
        else:
            raise ValueError('Invalid date string provided: {}'.format(date))
    elif isinstance(date, np.datetime64):
        return date.item().year
    else:
        return date.year


Instruction:
Write a Python 3 script for
converting a datetime - like object to the index s date type.

Response:
def maybe_convert_to_index_date_type(index, date):
    """Convert a datetime-like object to the index's date type.

    Datetime indexing in xarray can be done using either a pandas
    DatetimeIndex or a CFTimeIndex.  Both support partial-datetime string
    indexing regardless of the calendar type of the underlying data;
    therefore if a string is passed as a date, we return it unchanged.  If a
    datetime-like object is provided, it will be converted to the underlying
    date type of the index.  For a DatetimeIndex that is np.datetime64; for a
    CFTimeIndex that is an object of type cftime.datetime specific to the
    calendar used.

    Parameters
    ----------
    index : pd.Index
        Input time index
    date : datetime-like object or str
        Input datetime

    Returns
    -------
    date of the type appropriate for the time index of the Dataset
    """
    if isinstance(date, str):
        return date

    if isinstance(index, pd.DatetimeIndex):
        if isinstance(date, np.datetime64):
            return date
        else:
            return np.datetime64(str(date))
    else:
        date_type = index.date_type
        if isinstance(date, date_type):
            return date
        else:
            if isinstance(date, np.datetime64):
                # Convert to datetime.date or datetime.datetime object
                date = date.item()

            if isinstance(date, datetime.date):
                # Convert to a datetime.datetime object
                date = datetime.datetime.combine(
                    date, datetime.datetime.min.time())

            return date_type(date.year, date.month, date.day, date.hour,
                             date.minute, date.second, date.microsecond)


Instruction:
Write a Python 3 function that can
construct the mask that defines a region on a given data s grid.

Response:
def _make_mask(self, data, lon_str=LON_STR, lat_str=LAT_STR):
        """Construct the mask that defines a region on a given data's grid."""
        mask = False
        for west, east, south, north in self.mask_bounds:
            if west < east:
                mask_lon = (data[lon_str] > west) & (data[lon_str] < east)
            else:
                mask_lon = (data[lon_str] < west) | (data[lon_str] > east)
            mask_lat = (data[lat_str] > south) & (data[lat_str] < north)
            mask |= mask_lon & mask_lat
        return mask