예제 #1
0
def pastMonthObs():  #gets the obs from Mesopy from the last month
    d = datetime.now() - timedelta(
        1
    )  #going back into last month, because we want to look back on the month that just passed
    lastmonth = '%02d' % d.month  #so the month is formatted correctly
    year = '%04d' % d.year
    lastday = '%02d' % d.day
    start = str(year) + str(lastmonth) + str('01') + '0000'  #start at 00 UTC
    end = str(year) + str(lastmonth) + str(
        lastday) + '2359'  #end at end of month

    m = Meso(token=MesoPy_token)
    data = []
    time = m.timeseries(stid='kmsn', start=start, end=end)
    kmsn = time['STATION'][0]  #KMSN station
    rawtemps = kmsn['OBSERVATIONS']['air_temp_set_1']
    rawobstime = kmsn['OBSERVATIONS']['date_time']
    time = []
    temps = []  #in fahrenheit
    for i in range(len(rawobstime)):
        t = str(rawobstime[i]).replace('T', ' ').replace('Z', '')
        dt = datetime.strptime(t, "%Y-%m-%d %H:%M:%S")
        time.append(mdates.date2num(dt))
        temps.append('%.2f' % float(rawtemps[i] * 9 / 5 +
                                    32))  #converts from celsius to fahrenheit

    return temps, time
예제 #2
0
def retrieve_mesowest_observations(meso_token, tm_start, tm_end, glat, glon):
    """
    Retrieve observation data from Mesowest and repackage them as a time-indexed
    dictionary of lists of observations.

    :param meso_token: the mesowest API access token
    :param tm_start: the start of the observation window
    :param tm_end: the end of the observation window
    :param glat: the lattitudes of the grid points
    :param glon: the longitudes of the grid points
    """
    def decode_meso_time(t):
        # example: '2016-03-30T00:30:00Z'
        return datetime.strptime(t,
                                 '%Y-%m-%dT%H:%M:%SZ').replace(tzinfo=pytz.UTC)

    def meso_time(dt):
        # example: 201603311600
        return '%04d%02d%02d%02d%02d' % (dt.year, dt.month, dt.day, dt.hour,
                                         dt.minute)

    # the bbox for mesowest is: (min(lon), min(lat), max(lon), max(lat)).
    min_lat, max_lat = np.amin(glat), np.amax(glat)
    min_lon, max_lon = np.amin(glon), np.amax(glon)

    # retrieve data from Mesowest API (http://mesowest.org/api/)
    m = Meso(meso_token)
    meso_obss = m.timeseries(meso_time(tm_start - timedelta(minutes=30)),
                             meso_time(tm_end + timedelta(minutes=30)),
                             showemptystations='0',
                             bbox='%g,%g,%g,%g' %
                             (min_lon, min_lat, max_lon, max_lat),
                             vars='fuel_moisture')

    # repackage all the observations into a time-indexed structure which groups
    # observations at the same time together
    obs_data = {}
    for stinfo in meso_obss['STATION']:
        st_lat, st_lon = float(stinfo['LATITUDE']), float(stinfo['LONGITUDE'])
        elev = float(stinfo['ELEVATION']) / 3.2808
        ngp = find_closest_grid_point(st_lon, st_lat, glon, glat)
        dts = [
            decode_meso_time(x) for x in stinfo['OBSERVATIONS']['date_time']
        ]
        if 'fuel_moisture_set_1' in stinfo['OBSERVATIONS']:
            fms = stinfo['OBSERVATIONS']['fuel_moisture_set_1']

            for ts, fm_obs in zip(dts, fms):
                if fm_obs is not None:
                    o = FM10Observation(ts, st_lat, st_lon, elev,
                                        float(fm_obs) / 100., ngp)
                    obs_t = obs_data.get(ts, [])
                    obs_t.append(o)
                    obs_data[ts] = obs_t

    return obs_data
예제 #3
0
def retrieve_mesowest_observations(meso_token, tm_start, tm_end, glat, glon):
    """
    Retrieve observation data from Mesowest and repackage them as a time-indexed
    dictionary of lists of observations.

    :param meso_token: the mesowest API access token
    :param tm_start: the start of the observation window
    :param tm_end: the end of the observation window
    :param glat: the lattitudes of the grid points
    :param glon: the longitudes of the grid points
    """
    def decode_meso_time(t):
        # example: '2016-03-30T00:30:00Z'
        return datetime.strptime(t, '%Y-%m-%dT%H:%M:%SZ').replace(tzinfo=pytz.UTC)

    def meso_time(dt):
        # example: 201603311600
        return '%04d%02d%02d%02d%02d' % (dt.year, dt.month, dt.day, dt.hour, dt.minute)
        
    # the bbox for mesowest is: (min(lon), min(lat), max(lon), max(lat)).
    min_lat, max_lat = np.amin(glat), np.amax(glat)
    min_lon, max_lon = np.amin(glon), np.amax(glon)

    # retrieve data from Mesowest API (http://mesowest.org/api/)
    m = Meso(meso_token)
    meso_obss = m.timeseries(meso_time(tm_start - timedelta(minutes=30)),
                          meso_time(tm_end + timedelta(minutes=30)),
                          showemptystations = '0', bbox='%g,%g,%g,%g' % (min_lon, min_lat, max_lon, max_lat),
                          vars='fuel_moisture')


    # repackage all the observations into a time-indexed structure which groups
    # observations at the same time together
    obs_data = {}
    for stinfo in meso_obss['STATION']:
        st_lat, st_lon = float(stinfo['LATITUDE']), float(stinfo['LONGITUDE'])
        elev = float(stinfo['ELEVATION']) / 3.2808
        ngp = find_closest_grid_point(st_lon, st_lat, glon, glat)
        dts = [decode_meso_time(x) for x in stinfo['OBSERVATIONS']['date_time']]
        if 'fuel_moisture_set_1' in stinfo['OBSERVATIONS']:
            fms = stinfo['OBSERVATIONS']['fuel_moisture_set_1']

            for ts,fm_obs in zip(dts,fms):
                if fm_obs is not None:
                    o = FM10Observation(ts,st_lat,st_lon,elev,float(fm_obs)/100.,ngp)
                    obs_t = obs_data.get(ts, [])
                    obs_t.append(o)
                    obs_data[ts] = obs_t

    return obs_data
예제 #4
0
def build_pd(stn_id):
    key = 'b1c91e501782441d97ac056e2501b5b0'
    m = Meso(token=key)
    time = m.timeseries(stid=stn_id, start='199801010000', end='201801010000')
    ob = time['STATION'][0]
    temp = np.expand_dims(np.array(ob['OBSERVATIONS']['air_temp_set_1'],
                                   dtype=np.float),
                          axis=1)
    wind_dir = np.expand_dims(np.array(
        ob['OBSERVATIONS']['wind_direction_set_1'], dtype=np.float),
                              axis=1) * units.degrees
    wind_spd = np.expand_dims(np.array(ob['OBSERVATIONS']['wind_speed_set_1'],
                                       dtype=np.float),
                              axis=1) * 1.9438445
    wind_max = np.expand_dims(np.array(
        ob['OBSERVATIONS']['peak_wind_speed_set_1'], dtype=np.float),
                              axis=1) * 1.9438445
    u, v = mpcalc.get_wind_components(wind_spd, wind_dir)
    rel_hum = np.expand_dims(np.array(
        ob['OBSERVATIONS']['relative_humidity_set_1'], dtype=np.float),
                             axis=1)

    dates = ob['OBSERVATIONS']['date_time']
    years = float(dates[0][0:4])
    months = float(dates[0][5:7])
    hours = float(dates[0][8:10])
    days = float(dates[0][11:13])

    for i in range(len(dates) - 1):
        years = np.vstack((years, float(dates[i + 1][0:4])))
        months = np.vstack((months, float(dates[i + 1][5:7])))
        days = np.vstack((days, float(dates[i + 1][8:10])))
        hours = np.vstack((hours, float(dates[i + 1][11:13])))

    minutes = np.expand_dims(np.ones(len(hours)) * 55.0, axis=1)
    cols = [
        'Year', 'Month', 'Day', 'Hour', 'Minutes', 'Temp', 'RH', 'Dir', 'Spd',
        'Max', 'U', 'V'
    ]
    data = np.hstack((years, months, days, hours, minutes, temp, rel_hum,
                      wind_dir, wind_spd, wind_max, u, v))
    data = pd.DataFrame(data=data, columns=cols)
    pickle.dump(data, open('../Data/pickles/' + stn_id + '_20yr_RAWS.p', 'wb'))
    return data
예제 #5
0
variables = m.variables()

# This returns a climatology for Denver from Apr 26 OOz to Apr 27 OOz
climate = m.climatology(stid='kden',
                        startclim='04260000',
                        endclim='04270000',
                        units='precip|in')

# Fetches the latest obs for Fort Collins airport within 30 min of Apr 26 18z
attime = m.attime(stid='kfnl', attime='201504261800', within='30')

# Or just get the latest observation within the last 15 minutes
latest = m.latest(stid='kfnl', within='15')

# Returns a time series from Fort Collins airport from Apr 26 18z to Apr 26 23z
time = m.timeseries(stid='kfnl', start='201504261800', end='201504262300')

# Returns the precip obs from Fort Collins airport from Apr 26 18z to Apr 27 12z
precip = m.precip(stid='kfnl',
                  start='201504261800',
                  end='201504271200',
                  units='precip|in')

# Learn more about all of the networks in MesoWest with the networks() func
networks = m.networks()

# Or explore the categories MesoWest networks belong to
nettypes = m.networktypes()

# You can obtain time series statistics for any station
stats = m.time_stats(stid='mtmet',
예제 #6
0
vname_1 = []
vname_2 = []
vname_3 = []
vlabel = []
mean_obs = []
mean1 = []
mean2 = []
mean3 = []

x_list = []
y_list = []

# Iterate over dictionary to make time series plots of each variable for each station
for i in stations:
    # Return a time series from Aug 28 00z to Sep 9 23z for each station
    mw_data = m.timeseries(stid=i,start=start_t, end=end_t,vars=var_list,obtimezone=tz)
    
    # Skip station if the data is NoneType
    if mw_data is None:
        continue
    
    # All data for a station
    x = mw_data['STATION'][0]

    # Only keep variables of interest
    all_var = list(x['SENSOR_VARIABLES'])
    new_list = []
    for item in all_var:
        if item in var_list:
            new_list.append(item)
    
예제 #7
0
stations = m.metadata(state='CO', county='Larimer')

# Calling variables() returns all possible sensor variables at stations
variables = m.variables()

# This returns a climatology for Denver from Apr 26 OOz to Apr 27 OOz
climate = m.climatology(stid='kden', startclim='04260000', endclim='04270000', units='precip|in')

# Fetches the latest obs for Fort Collins airport within 30 min of Apr 26 18z
attime = m.attime(stid='kfnl', attime='201504261800', within='30')

# Or just get the latest observation within the last 15 minutes
latest = m.latest(stid='kfnl', within='15')

# Returns a time series from Fort Collins airport from Apr 26 18z to Apr 26 23z
time = m.timeseries(stid='kfnl', start='201504261800', end='201504262300')

# Returns the precip obs from Fort Collins airport from Apr 26 18z to Apr 27 12z
precip = m.precip(stid='kfnl', start='201504261800', end='201504271200', units='precip|in')

# Learn more about all of the networks in MesoWest with the networks() func
networks = m.networks()

# Or explore the categories MesoWest networks belong to
nettypes = m.networktypes()

# You can obtain time series statistics for any station
stats = m.time_stats(stid='mtmet', start='201403240000', end='201403280000', type='all')

# Or get climatology stats for a station (remember to change the date!)
clim_stats = m.climate_stats(stid='mtmet', startclim='03240000', endclim='03280000', type='all')
예제 #8
0
def retrieve_mesowest_observations(meso_token, tm_start, tm_end, glat, glon,
                                   ghgt):
    """
    Retrieve observation data from Mesowest and repackage them as a time-indexed
    dictionary of lists of observations.  
    :param meso_token: the mesowest API access token or list of them
    :param tm_start: the start of the observation window
    :param tm_end: the end of the observation window
    :param glat: the lattitudes of the grid points
    :param glon: the longitudes of the grid points
    :param ghgt: the elevation of the grid points
    """
    def decode_meso_time(t):
        # example: '2016-03-30T00:30:00Z'
        return datetime.strptime(t,
                                 '%Y-%m-%dT%H:%M:%SZ').replace(tzinfo=pytz.UTC)

    def meso_time(dt):
        # example: 201603311600
        return '%04d%02d%02d%02d%02d' % (dt.year, dt.month, dt.day, dt.hour,
                                         dt.minute)

    # the bbox for mesowest is: (min(lon), min(lat), max(lon), max(lat)).
    min_lat, max_lat = np.amin(glat), np.amax(glat)
    min_lon, max_lon = np.amin(glon), np.amax(glon)

    # retrieve data from Mesonet API (http://api.mesowest.net/)
    try:
        logging.info(
            'retrieve_mesowest_observations: retrieving data using MesoDB')
        db = mesoDB('ingest/MesoDB', meso_token)
        db.update['startTime'] = tm_start - timedelta(minutes=30)
        db.update['endTime'] = tm_end + timedelta(minutes=30)
        db.params['startTime'] = tm_start - timedelta(minutes=30)
        db.params['endTime'] = tm_end + timedelta(minutes=30)
        db.params['longitude1'] = min_lon
        db.params['longitude2'] = max_lon
        db.params['latitude1'] = min_lat
        db.params['latitude2'] = max_lat
        df = db.get_DB().dropna(subset=['fm10'])
        st = db.sites()
        if not len(df):
            logging.info(
                'retrieve_mesowest_observations: no data for the query specified'
            )
            return {}
        logging.info(
            'retrieve_mesowest_observations: re-packaging the observations')
        obs_data = {}
        for stid, data in df.groupby('STID'):
            if len(data):
                st_data = st.loc[stid]
                st_lat, st_lon = float(st_data['LATITUDE']), float(
                    st_data['LONGITUDE'])
                ngp = find_closest_grid_point(st_lon, st_lat, glon, glat)
                st_elev = st_data['ELEVATION']
                if st_elev is None:
                    elev = ghgt[ngp]
                else:
                    elev = float(st_data['ELEVATION']) / 3.2808
                dts = data.datetime.dt.to_pydatetime()
                fms = np.array(data.fm10)
                for ts, fm_obs in zip(dts, fms):
                    if fm_obs is not None:
                        o = FM10Observation(ts, st_lat, st_lon, elev,
                                            float(fm_obs) / 100., ngp)
                        obs_t = obs_data.get(ts, [])
                        obs_t.append(o)
                        obs_data[ts] = obs_t
        return obs_data
    except:
        logging.warning(
            'retrieve_mesowest_observations: failed with exception {}')
        logging.info(
            'retrieve_mesowest_observations: retrieving data using Meso instead'
        )
        if isinstance(meso_token, str):
            meso_tokens = [meso_token]
            n_tokens = 1
        else:
            meso_tokens = meso_token
            n_tokens = len(meso_tokens)
        for tn, meso_token in enumerate(meso_tokens):
            m = Meso(meso_token)
            logging.info("Retrieving fuel moisture from %s to %s" %
                         (meso_time(tm_start - timedelta(minutes=30)),
                          meso_time(tm_end + timedelta(minutes=30))))
            logging.info("bbox=' %g,%g,%g,%g'" %
                         (min_lon, min_lat, max_lon, max_lat))
            try:
                meso_obss = m.timeseries(
                    meso_time(tm_start - timedelta(minutes=30)),
                    meso_time(tm_end + timedelta(minutes=30)),
                    showemptystations='0',
                    bbox='%g,%g,%g,%g' % (min_lon, min_lat, max_lon, max_lat),
                    vars='fuel_moisture')
                break
            except Exception as e:
                if tn == n_tokens - 1:
                    raise MesoPyError(
                        'Could not connect to the API. Probably the token(s) usage for this month is full.'
                    )
                else:
                    logging.warning(
                        'Could not connect to the API. Probably the token usage for this month is full. Trying next token...'
                    )

        if meso_obss is None:
            logging.info(
                'retrieve_mesowest_observations: Meso.timeseries returned None'
            )
            return {}

        logging.info(
            'retrieve_mesowest_observations: re-packaging the observations')
        # repackage all the observations into a time-indexed structure which groups
        # observations at the same time together
        obs_data = {}
        for stinfo in meso_obss['STATION']:
            st_lat, st_lon = float(stinfo['LATITUDE']), float(
                stinfo['LONGITUDE'])
            ngp = find_closest_grid_point(st_lon, st_lat, glon, glat)
            st_elev = stinfo['ELEVATION']
            if st_elev is None:
                elev = ghgt[ngp]
            else:
                elev = float(stinfo['ELEVATION']) / 3.2808
            dts = [
                decode_meso_time(x)
                for x in stinfo['OBSERVATIONS']['date_time']
            ]
            if 'fuel_moisture_set_1' in stinfo['OBSERVATIONS']:
                fms = stinfo['OBSERVATIONS']['fuel_moisture_set_1']
                for ts, fm_obs in zip(dts, fms):
                    if fm_obs is not None:
                        o = FM10Observation(ts, st_lat, st_lon, elev,
                                            float(fm_obs) / 100., ngp)
                        obs_t = obs_data.get(ts, [])
                        obs_t.append(o)
                        obs_data[ts] = obs_t

    return obs_data
def retrieve_wxobs_synopticlabs(
        api_key,
        data_path,
        station_id='knyc',
        st_time='201801010000',
        ed_time='201801020000',
        vbl_list=['date_time', 'air_temp', 'relative_humidity'],
        download_new=False):
    """
    Function to retrieve timeseries weather observations from an observation site. Uses the
    MesoWest/SynopticLabs API to retrieve the observations.

    PARAMETERS:
    *********** 

    api_key: SynopticLabs api_key.

    data_path: Path to directory in which we want to save the observations.

    station_id: Four-letter station id.

    st_time: Start time for observations, in format 'YYYYMMDDhhmm'. 

    ed_time: End time for observations, in format 'YYYYMMDDhhmm'. 

    vbl_list: List of variables to retrieve from SynopticLabs. 

    download_new: Boolean, re-download data from SynopticLabs if True. 

    OUTPUTS:
    ********

    data_ts: Data structure returned from API request. 

    path_name: File path/name for data structure that was just retrieved.
    """
    def get_synopticlabs_token(api_key):
        request_generate_token = 'http://api.mesowest.net/v2/auth?apikey=' + api_key
        api_out = requests.get(request_generate_token).text
        token_dict = json.loads(api_out)
        token_synopticlabs = token_dict['TOKEN']
        return token_synopticlabs

    file_name = 'wxobs_' + station_id + '_' + st_time + '_' + ed_time + '.pkl'

    if download_new:

        token_synopticlabs = get_synopticlabs_token(api_key)
        m = Meso(token=token_synopticlabs)
        data_ts = m.timeseries(stid=station_id,
                               start=st_time,
                               end=ed_time,
                               vars=vbl_list)
        pickle.dump(data_ts, open(os.path.join(data_path, file_name), 'wb'))

    else:

        try:
            data_ts = pickle.load(
                open(os.path.join(data_path, file_name), 'rb'))
        except:
            raise (OSError('File not found: ' + file_name))

    return data_ts, os.path.join(data_path, file_name)
예제 #10
0
m = Meso(token=MyToken)
#q = m.timeseries(start=StartTime,end=EndTime,stid='CNST2')#,vars='wind_speed,pressure')
#print(type(q['STATION']))
#print type(q['STATION'])
##for l in q['STATION']:
##    for k,v in l.items():
##        print k,v
#meso_df = pd.DataFrame.from_dict(q,orient='columns')
#meso_df
#print m.variables()
'''
SENSOR_VARIABLES {u'wind_speed': {u'wind_speed_set_1': {u'position': u''}},
u'date_time': {u'date_time': {}},
u'solar_radiation': {u'solar_radiation_set_1': {u'position': u''}},
u'wind_gust': {u'wind_gust_set_1': {u'position': u''}},
u'pressure': {u'pressure_set_1': {u'position': u''}},
u'precip_accum_one_minute': {u'precip_accum_one_minute_set_1': {u'position': u''}},
u'wind_direction': {u'wind_direction_set_1': {u'position': u''}},
u'wind_chill': {u'wind_chill_set_1d': {u'derived_from': [u'air_temp_set_1', u'wind_speed_set_1']}},
u'wind_cardinal_direction': {u'wind_cardinal_direction_set_1d': {u'derived_from': [u'wind_direction_set_1']}},
u'relative_humidity': {u'relative_humidity_set_1': {u'position': u''}},
u'sea_level_pressure': {u'sea_level_pressure_set_1d': {u'derived_from': [u'pressure_set_1', u'air_temp_set_1', u'relative_humidity_set_1']}},
u'air_temp': {u'air_temp_set_1': {u'position': u''}},
u'dew_point_temperature': {u'dew_point_temperature_set_1d': {u'derived_from': [u'air_temp_set_1', u'relative_humidity_set_1']}},
u'altimeter': {u'altimeter_set_1d': {u'derived_from': [u'pressure_set_1']}}}
'''
q_asos = m.timeseries(start=StartTime, end=EndTime,
                      stid='KCLL')  #,vars='wind_speed,pressure')
#print type(q_asos['STATION'])
print q_asos['STATION'][0]['SENSOR_VARIABLES']
예제 #11
0
#varList = "precip_accum_one_hour_set_1, wind_direction_set_1, air_temp_high_6_hour_set_1, weather_cond_code_set_1, relative_humidity_set_1,precip_accum_three_hour_set_1,cloud_layer_1_code_set_1,air_temp_high_24_hour_set_1,precip_accum_six_hour_set_1,air_temp_low_24_hour_set_1,dew_point_temperature_set_1,date_time,peak_wind_direction_set_1,wind_speed_set_1,air_temp_set_1,wind_gust_set_1,cloud_layer_2_code_set_1,cloud_layer_3_code_set_1,peak_wind_speed_set_1,metar_set_1,precip_accum_24_hour_set_1,weather_condition_set_1d"
Units = 'precip|in,temp|F,speed|mph'
# #For FW13
# varList = ['wind_direction', 'weather_condition', 'wind_direction', 'precip_accum_one_hour', 'peak_wind_direction', 'wind_speed',
#         'relative_humidity', 'precip_accum_three_hour', 'dew_point_temperature', 'air_temp', 'wind_gust', 'peak_wind_speed', 'metar', 'precip_accum_24_hour']
#Just for FW9
#For historical it need f13 !(The peak wind and wind gust)
varList = [
    'wind_direction', 'weather_condition', 'wind_direction',
    'precip_accum_one_hour', 'peak_wind_direction', 'peak_wind_speed',
    'wind_speed', 'relative_humidity', 'precip_accum_three_hour',
    'dew_point_temperature', 'air_temp', 'metar', 'precip_accum_24_hour'
]
alldata = m.timeseries(stid=StationIDs,
                       start=StartTime,
                       end=EndTime,
                       vars=varList,
                       units=Units)
#alldata = json.dumps(alldata, sort_keys=True)
#print len(alldata['STATION'])

for stationobs in alldata['STATION']:
    obs_df_dict = stationobs['OBSERVATIONS']
    stnm = stationobs['STID']
    stid = Stations[stnm]
    print stnm, stid

    df = pandas.DataFrame.from_dict(obs_df_dict)
    #print df
    variablelist = list(df.columns)
    print variablelist
예제 #12
0
    # precipitation query will return total precipitation over the last 24 hours
    start, end = '201712111800', '201712121200'
    mwprecipdata = m.precip(stid=kbdistations,
                            start=start,
                            end=end,
                            units='precip|in')
    #precip = m.precip(stid='CDDT2', start='201709261800',end='201711271200', units='precip|in')
    #print(mwprecipdata)

    # temperature query will return all observations over the last 24 hours
    # Add vars for air_temp_high_6_hour

    mwtempdata = m.timeseries(stid=kbdistations,
                              start=start,
                              end=end,
                              vars='air_temp,air_temp_high_6_hour',
                              units='temp|F,precip|in')

    for ob in mwmetadata['STATION']:
        recentob = ob['PERIOD_OF_RECORD']['end'][:10]
        obid = ob['STID']
        stationsDict[obid]['RECENT_OBS'] = ob['PERIOD_OF_RECORD']['end']
        stationsDict[obid]['LONGITUDE'] = ob['LONGITUDE']
        stationsDict[obid]['LATITUDE'] = ob['LATITUDE']

        if recentob == comparedate:
            stationsDict[obid]['RECENT_OBS'] = "CURRENT"
            #print obid + " is current"

        #else:
예제 #13
0
def retr_wxobs_synopticlabs(api_key,
                            data_path,
                            station_id='knyc',
                            st_time='201801010000',
                            ed_time='201801020000',
                            download_new=False):
    """Function to retrieve timeseries weather observations from an observation site. Uses the 
    MesoWest/SynopticLabs API to retrieve the observations. 
    
    **********
    PARAMETERS
        api_key: SynopticLabs api_key. 
        data_path: Path to directory in which we want to save the observations. 
        station_id: Four-letter station id. 
        st_time: start time for observations, in format 'YYYYMMDDhhmm'
        ed_time: end time for observations, in format 'YYYYMMDDhhmm'
        
    OUTPUT: 
        obs_dict: Dictionary with station attributes, station observations, observation units, and 
                  quality control summary. 
        path_name: File path/name for data that was just retrieved. 
    """
    def get_synopticlabs_token(api_key):
        request_generate_token = 'http://api.mesowest.net/v2/auth?apikey=' + api_key
        api_out = requests.get(request_generate_token).text
        token_dict = json.loads(api_out)
        token_synopticlabs = token_dict['TOKEN']
        return token_synopticlabs

    def get_station_attrs(data_ts, station_attrs):
        station_info = {}
        for attr in station_attrs:
            station_info[attr] = data_ts['STATION'][0][attr]
        return station_info

    def get_station_obs(data_ts, vbl_list):
        station_data = {}
        station_data[vbl_list[0]] = data_ts['STATION'][0]['OBSERVATIONS'][
            vbl_list[0]]
        for vbl in vbl_list[1:]:
            station_data[vbl] = data_ts['STATION'][0]['OBSERVATIONS'][list(
                data_ts['STATION'][0]['SENSOR_VARIABLES'][vbl].keys())[0]]
        return station_data

    vbl_list = ['date_time', 'air_temp', 'relative_humidity']
    station_attrs = ['STID', 'ELEVATION', 'NAME', 'LONGITUDE', 'LATITUDE']
    file_name = 'wxobs_' + station_id + '_' + st_time + '_' + ed_time + '.npy'

    token_synopticlabs = get_synopticlabs_token(api_key)

    if download_new:
        # Retrieve the station data from API.
        m = Meso(token=token_synopticlabs)
        data_ts = m.timeseries(stid=station_id,
                               start=st_time,
                               end=ed_time,
                               vars=vbl_list[1:])

        # Put everything in a single dictionary.
        obs_dict = {}
        obs_dict['station_attrs'] = get_station_attrs(data_ts, station_attrs)
        obs_dict['station_obs'] = get_station_obs(data_ts, vbl_list)
        obs_dict['units'] = data_ts['UNITS']
        obs_dict['qc_summary'] = data_ts['QC_SUMMARY']

        # Save the dictionary
        np.save(os.path.join('.', 'data', file_name), obs_dict)

    else:

        # Load the dictionary
        try:
            obs_dict = np.load(os.path.join('.', 'data', file_name)).item()
        except:
            raise (OSError('File not found: ' + filename))

    return obs_dict, os.path.join(data_path, file_name)