Example #1
0
def transform_and_check_data(p, z, qv, wind_dir, wind_speed, th):
    """Quality check and convert units of Uinversity of Wyoming sound data

    :param p: pressure
    :param z: heights
    :param qv: mixing ration
    :param wind_dir: wind direction
    :param wind_speed: wind speed
    :param th: potential temperature
    :returns: pressure, heights, mixing ration, u wind, v wind and potential temperature

    This ingests data loaded from file owr web and culls invalid rows (NaN in certain colums)
    and quality checks the data.  Units are converted from the native uwyo data to the
    module standard SI units.
    """
    # clean up NaNs and mark invalid rows for deletion
    nk = len(z)
    for k in np.arange(nk):
        delete_rows = []
        if np.isnan(p[k]):
            delete_rows.append(k)
        if np.isnan(qv[k]):
            qv[k] = 0
        if np.isnan(wind_speed[k]):
            wind_speed[k] = wind_speed[k - 1]
        if np.isnan(wind_dir[k]):
            wind_dir[k] = wind_dir[k - 1]

    # delete invalid rows
    p = np.delete(p, delete_rows)
    z = np.delete(z, delete_rows)
    qv = np.delete(qv, delete_rows)
    wind_dir = np.delete(wind_dir, delete_rows)
    wind_speed = np.delete(wind_speed, delete_rows)
    th = np.delete(th, delete_rows)

    # convert ingested units to our package standard units
    nk = len(z)
    p = p * 100.  # hPa to Pa
    qv = qv / 1000.  # g/kg to kg/kg
    wind_speed = wind_speed * 0.51444  # kts to m/s

    # convert wind direction,speed to u,v components
    u = np.empty(nk, np.float32)
    v = np.empty(nk, np.float32)
    for k in np.arange(nk):
        u[k], v[k] = dynamics.wind_deg_to_uv(wind_dir[k], wind_speed[k])

    p[np.isnan(p)] = 0
    qv[np.isnan(qv)] = 0
    u[np.isnan(u)] = 0
    v[np.isnan(v)] = 0
    #reutrn data
    return (p, z, qv, u, v, th)
Example #2
0
def transform_and_check_data(p, z, qv, wind_dir, wind_speed, th):
    """Quality check and convert units of Uinversity of Wyoming sound data

    :param p: pressure
    :param z: heights
    :param qv: mixing ration
    :param wind_dir: wind direction
    :param wind_speed: wind speed
    :param th: potential temperature
    :returns: pressure, heights, mixing ration, u wind, v wind and potential temperature

    This ingests data loaded from file owr web and culls invalid rows (NaN in certain colums)
    and quality checks the data.  Units are converted from the native uwyo data to the
    module standard SI units.
    """
    # clean up NaNs and mark invalid rows for deletion
    nk = len(z)
    for k in np.arange(nk):
        delete_rows = []
        if np.isnan(p[k]):
            delete_rows.append(k)
        if np.isnan(qv[k]):
            qv[k] = 0
        if np.isnan(wind_speed[k]):
            wind_speed[k] = wind_speed[k-1]
        if np.isnan(wind_dir[k]):
            wind_dir[k] = wind_dir[k-1]

    # delete invalid rows
    p = np.delete(p,delete_rows)
    z = np.delete(z,delete_rows)
    qv = np.delete(qv,delete_rows)
    wind_dir = np.delete(wind_dir, delete_rows)
    wind_speed = np.delete(wind_speed, delete_rows)
    th = np.delete(th, delete_rows)

    # convert ingested units to our package standard units
    nk = len(z)
    p = p * 100. # hPa to Pa
    qv = qv / 1000. # g/kg to kg/kg
    wind_speed = wind_speed * 0.51444  # kts to m/s

    # convert wind direction,speed to u,v components
    u = np.empty(nk, np.float32)
    v = np.empty(nk, np.float32)
    for k in np.arange(nk):
        u[k], v[k] = dynamics.wind_deg_to_uv(wind_dir[k], wind_speed[k])

    #reutrn data
    return (p, z, qv, u, v, th)
Example #3
0
def plot_sounding_data_csv(filename, output):
    """Plot SkewT from a CSV sounding data file
    
        :param filename: The name of the file to open.
        :type filename: str
        :param output: The name of the file to output plot
        :type output: str

        The datafile format is CSV with the following columns: 

        - pressure (mb)
        - height (m)
        - temperature (C)
        - dew point (C)
        - wind direction (degrees)
        - wind speed (m/s)
        
        Missing values should be filled with the value -9999.00
        """
    p, z, T, Td, wdir, wspd = np.loadtxt(filename, delimiter=',', unpack=True)
    # Pressure to Pa
    p = p * 100.

    # z to km
    #z = z / 1000.

    # interpolate missing wind

    nk = len(z)
    u = np.empty(nk, np.float32)
    v = np.empty(nk, np.float32)

    for k in range(nk):
        if wdir[k] == -9999. and wspd[k] == -9999.:
            u[k] = v[k] = -9999.
        else:
            u[k], v[k] = dyn.wind_deg_to_uv(wdir[k], wspd[k])

        #print('{0:5.2f} {1:5.2f} = {2:5.2f} {3:5.2f}'.format(wdir[k], wspd[k], u[k], v[k]))

    _z = np.empty(2, np.float32)
    _u = np.empty(2, np.float32)
    _v = np.empty(2, np.float32)
    print('INTERPOLATING')
    for k in range(nk):
        if wdir[k] == -9999. and wspd[k] == -9999.:
            kb = ke = k
            while kb >= 0 and wdir[kb] == -9999. and wspd[kb] == -9999.:
                kb -= 1
            while ke <= nk - 1 and wdir[ke] == -9999. and wspd[ke] == -9999.:
                ke += 1

            # everything in bounds
            if kb >= 0 and ke <= nk - 1:
                _z[0] = z[kb]
                _z[1] = z[ke]
                _u[0] = u[kb]
                _u[1] = u[ke]
                _v[0] = v[kb]
                _v[1] = v[ke]

                u[k] = pymeteo.interp.linear(_z, _u, z[k])
                v[k] = pymeteo.interp.linear(_z, _v, z[k])

            elif kb < 0:
                u[k] = u[ke]
                v[k] = v[ke]
            elif ke > nk - 1:
                u[k] = u[kb]
                v[k] = v[kb]

    for k in range(nk):
        # kt to m/s
        u[k] = u[k] * 0.5144444
        v[k] = v[k] * 0.5144444
    #   print('{0:5.2f} {1:5.2f} = {2:5.2f} {3:5.2f}'.format(wdir[k], wspd[k], u[k], v[k]))

    # calc theta
    th = np.empty(nk, np.float32)
    # calc qv
    qv = np.empty(nk, np.float32)
    for k in range(nk):
        th[k] = met.theta(T[k] + met.T00, p[k])
        w = met.es(Td[k] + met.T00) / met.es(T[k] + met.T00)
        pp = met.es(T[k] + met.T00) / p[k]
        qv[k] = 0.622 * pp * w
        #qv[k] = met.es(Td[k]+met.T00) / (met.Rv * (T[k]+met.T00))

    #print(z, th, p, qv, u, v)

    plot(None, z, th, p, qv, u, v, output, title='Sounding Data')
Example #4
0
def processDataSet(data):
    print("[+] Writing data into temporary file")
    tdata = tempfile.NamedTemporaryFile()
    tdata.write(data.read())
    print("[-] Data written to {0}".format(tdata.name))
    print("[+] Opening data as NetCDF")
    d = data.read()
    with netCDF4.Dataset(tdata.name, mode='r') as nc:
        print("[-] Dataset open with")

        _z = nc["altitude"][:]
        _T = nc["temperature"][:]
        _qv = nc["waterVaporMR"][:]
        windSpeed = nc["windSpeed"][:]
        windDir = nc["windDir"][:]
        _lon = nc["longitude"][:]
        _lat = nc["latitude"][:]
        flag = nc["sounding_flag"][:]
        _airport = nc["sounding_airport_id"][:]
        time = nc["soundingSecs"][:]

        print("[-] {0} Records".format(len(_z)))
        #conversions
        _p = thermo.p_from_pressure_altitude(_z, _T)
        _u, _v = dynamics.wind_deg_to_uv(windDir, windSpeed)
        _th = thermo.theta(_T, _p)

        # split the arrays when the flag changes sign
        splits = np.where(np.diff(time))[0] + 1

        _z = np.split(_z, splits)
        _p = np.split(_p, splits)
        _th = np.split(_th, splits)
        _qv = np.split(_qv, splits)
        _u = np.split(_u, splits)
        _v = np.split(_v, splits)
        _lat = np.split(_lat, splits)
        _lon = np.split(_lon, splits)
        _airport = np.split(_airport, splits)
        time = np.split(time, splits)
        flag = np.split(flag, splits)

        print("[-] Found {0} profiles".format(len(_z)))

        #re-shape data
        outputData = []
        for i in range(len(_z)):
            ts = time[i].compressed()
            if len(ts) == 0:
                # profiles without timestamps invalid?
                continue

            profileDir = flag[i][0]
            if (profileDir == 0):
                continue

            z = _z[i].filled()
            p = _p[i].filled()
            th = _th[i].filled()
            qv = _qv[i].filled()
            u = _u[i].filled()
            v = _v[i].filled()
            lat = _lat[i].filled()
            lon = _lon[i].filled()
            airport = getAirportByCode(_airport[i][0])
            profileData = {
                "i": i,
                "n": len(z),
                "z": z if profileDir > 0 else z[::-1],
                "p": p if profileDir > 0 else p[::-1],
                "th": th if profileDir > 0 else th[::-1],
                "qv": qv if profileDir > 0 else qv[::-1],
                "u": u if profileDir > 0 else u[::-1],
                "v": v if profileDir > 0 else v[::-1],
                "lat": lat if profileDir > 0 else lat[::-1],
                "lon": lon if profileDir > 0 else lon[::-1],
                "airport": airport,
                "time": datetime.utcfromtimestamp(ts.mean()).strftime("%H%MZ"),
                "flag": profileDir
            }
            outputData.append(profileData)

        return outputData
Example #5
0
def plot_sounding_data_csv(filename, output):
        """Plot SkewT from a CSV sounding data file
    
        :param filename: The name of the file to open.
        :type filename: str
        :param output: The name of the file to output plot
        :type output: str

        The datafile format is CSV with the following columns: 

        - pressure (mb)
        - height (m)
        - temperature (C)
        - dew point (C)
        - wind direction (degrees)
        - wind speed (m/s)
        
        Missing values should be filled with the value -9999.00
        """
        p,z,T,Td,wdir,wspd = np.loadtxt(filename, delimiter=',',  unpack=True)
        # Pressure to Pa
        p = p * 100.

        # z to km
        #z = z / 1000.
        
        # interpolate missing wind

        nk = len(z)
        u = np.empty(nk, np.float32)
        v = np.empty(nk, np.float32)

        for k in range(nk):
           if wdir[k] == -9999. and wspd[k] == -9999.:
              u[k] = v[k] = -9999.
           else:
              u[k], v[k] = dyn.wind_deg_to_uv(wdir[k], wspd[k])

           #print('{0:5.2f} {1:5.2f} = {2:5.2f} {3:5.2f}'.format(wdir[k], wspd[k], u[k], v[k]))
           
        _z = np.empty(2,np.float32)
        _u = np.empty(2,np.float32)
        _v = np.empty(2,np.float32)
        print('INTERPOLATING')
        for k in range(nk):
           if wdir[k] == -9999. and wspd[k] == -9999.:
              kb = ke = k
              while kb >= 0 and wdir[kb] == -9999. and wspd[kb] == -9999.:
                 kb -= 1
              while ke <= nk-1 and wdir[ke] == -9999. and wspd[ke] == -9999.:
                 ke += 1

              # everything in bounds
              if kb >= 0 and ke <= nk-1:
                 _z[0] = z[kb]
                 _z[1] = z[ke]
                 _u[0] = u[kb]
                 _u[1] = u[ke]
                 _v[0] = v[kb]
                 _v[1] = v[ke]
                 
                 u[k] = pymeteo.interp.linear(_z, _u, z[k])
                 v[k] = pymeteo.interp.linear(_z, _v, z[k])

              elif kb < 0:
                 u[k] = u[ke]
                 v[k] = v[ke] 
              elif ke > nk-1:
                 u[k] = u[kb]
                 v[k] = v[kb] 

        for k in range(nk):
           # kt to m/s
           u[k] = u[k] * 0.5144444
           v[k] = v[k] * 0.5144444
        #   print('{0:5.2f} {1:5.2f} = {2:5.2f} {3:5.2f}'.format(wdir[k], wspd[k], u[k], v[k]))

        # calc theta
        th = np.empty(nk, np.float32)
        # calc qv
        qv = np.empty(nk, np.float32)
        for k in range(nk):
           th[k] = met.theta(T[k]+met.T00, p[k]) 
           w = met.es(Td[k]+met.T00) / met.es(T[k]+met.T00)
           pp = met.es(T[k]+met.T00) / p[k]
           qv[k] = 0.622 * pp * w
           #qv[k] = met.es(Td[k]+met.T00) / (met.Rv * (T[k]+met.T00))

        #print(z, th, p, qv, u, v)

        plot(None, z, th, p, qv, u, v, output, title='Sounding Data')