def find_station(*args): stns = 0 if len(args) == 1: station_name = args[0] print("LOOKUP BY STATION NAME: ", station_name) station_name = station_name.upper() ghcnd_stations = gp.get_ghcnd_stations() stns = list( filter(lambda x: re.search(station_name, x), ghcnd_stations[:, 5])) print( "GHCND ID LAT LON ELEV ST STATION NAME") print( "###############################################################") for station_counter in range(len(stns)): ghcnd_meta = ghcnd_stations[ghcnd_stations[:, 5] == stns[station_counter]] print(ghcnd_meta[0][0], ghcnd_meta[0][1], ghcnd_meta[0][2], ghcnd_meta[0][3], ghcnd_meta[0][4], ghcnd_meta[0][5]) elif len(args) == 3: station_lat = args[0] station_lon = args[1] distance_limit = args[2] print("LOOKUP BY STATION LAT: ", station_lat, " LON: ", station_lon, " DIST LIMIT (mi): ", distance_limit) target_latlon = (float(station_lat), float(station_lon)) ghcnd_stations = gp.get_ghcnd_stations() print( "GHCND ID LAT LON ELEV ST STATION NAME") print( "###############################################################") for ghcnd_counter in range(ghcnd_stations[:, 0].size): candidate_latlon = (ghcnd_stations[ghcnd_counter][1], ghcnd_stations[ghcnd_counter][2]) dist = great_circle(target_latlon, candidate_latlon).miles if dist <= distance_limit: print(ghcnd_stations[ghcnd_counter][0], ghcnd_stations[ghcnd_counter][1], ghcnd_stations[ghcnd_counter][2], ghcnd_stations[ghcnd_counter][3], ghcnd_stations[ghcnd_counter][4], ghcnd_stations[ghcnd_counter][5]) else: print("USAGE\n NAME or\n LAT LON DIST") return None return None
def find_station(*args): stns=0 if len(args) ==1: station_name=args[0] print("LOOKUP BY STATION NAME: ",station_name) station_name=station_name.upper() ghcnd_stations=gp.get_ghcnd_stations() stns=filter(lambda x: re.search(station_name,x), ghcnd_stations[:,5]) print("GHCND ID LAT LON ELEV ST STATION NAME") print("###############################################################") for station_counter in xrange(len(stns)): ghcnd_meta = ghcnd_stations[ghcnd_stations[:,5]== stns[station_counter]] print(ghcnd_meta[0][0],ghcnd_meta[0][1],ghcnd_meta[0][2],ghcnd_meta[0][3],ghcnd_meta[0][4],ghcnd_meta[0][5]) elif len(args)==3: station_lat=args[0] station_lon=args[1] distance_limit=args[2] print("LOOKUP BY STATION LAT: ",station_lat," LON: ",station_lon, " DIST LIMIT (mi): ",distance_limit) target_latlon = (float(station_lat), float(station_lon)) ghcnd_stations=gp.get_ghcnd_stations() print("GHCND ID LAT LON ELEV ST STATION NAME") print("###############################################################") for ghcnd_counter in xrange(ghcnd_stations[:,0].size): candidate_latlon=(ghcnd_stations[ghcnd_counter][1], ghcnd_stations[ghcnd_counter][2]) dist=great_circle(target_latlon, candidate_latlon).miles if dist <= distance_limit: print(ghcnd_stations[ghcnd_counter][0],ghcnd_stations[ghcnd_counter][1],ghcnd_stations[ghcnd_counter][2],ghcnd_stations[ghcnd_counter][3],ghcnd_stations[ghcnd_counter][4],ghcnd_stations[ghcnd_counter][5]) else: print("USAGE\n NAME or\n LAT LON DIST") return None return None
def main(): ## get metadata file file (ghcnd-stations.txt) click.secho('>>> Get metadata file (ghcnd-stations.txt)', fg='green') gp.get_ghcnd_stations() ## get inventory file (ghcnd-inventory.txt) click.secho('>>> Get inventory file (ghcnd-inventory.txt)', fg='green') gp.get_ghcnd_inventory() ## find stations click.secho('>>> Find stations... Example: "NEW ORLEANS"', fg='green') gp.find_station("NEW ORLEANS") ## download click.secho( '>>> Download data in csv format after finding the target station ID... Example: "NEW ORLEANS LAKEFRONT AP" ', fg='green') gp.output_to_csv("USW00053917") ## read data click.secho('>>> Read data... Example: "NEW ORLEANS LAKEFRONT AP"', fg='green') data = pd.read_csv('USW00053917.csv') print(data.head()) print(data.tail()) # return return None
def output_to_netcdf(station_id): print "\nOUTPUTTING TO netCDF: ", station_id, ".nc" begin_year = 1700 end_year = datetime.datetime.now().year num_years = (end_year - begin_year) + 1 start_date = date(begin_year, 01, 01) end_date = date(end_year, 12, 31) # 5 Elements of GHCN-D num_elements = 5 tmax = 0 tmin = 1 prcp = 2 snow = 3 snwd = 4 # 3 Flags for each value num_flags = 3 # Measurement Flag (MFLAG) mflag = 0 mflag_codes = np.array( [ord(x) for x in ["B", "D", "H", "K", "L", "O", "P", "T", "W"]], dtype='b') mflag_meanings = np.array(["precipitation total formed from two 12 hour totals".replace(" ","_")+" ",\ "precipitation total formed from four six hour totals".replace(" ","_")+" ",\ "represents highest or lowest hourly temperature".replace(" ","_")+" ",\ "converted from knots".replace(" ","_")+" ",\ "temperature appears to be lagged with respect to reported hour of observation".replace(" ","_")+" ",\ "converted from oktas".replace(" ","_")+" ",\ "identified as missing presumed zero in DSI 3200 and 3206".replace(" ","_")+" ",\ "trace of precipitation snowfall or snow depth".replace(" ","_")+" ",\ "converted from 16 point WBAN code for wind direction".replace(" ","_")],\ dtype='str') # Quality Control Flag (QCFLAG) qcflag = 1 qcflag_codes = np.array([ ord(x) for x in ["D", "G", "I", "K", "L", "M", "N", "O", "R", "S", "T", "W", "X", "Z"] ], dtype='b') qcflag_meanings = np.array(["failed duplicate check".replace(" ","_")+" ",\ "failed gap check".replace(" ","_")+" ",\ "failed internal consistency check".replace(" ","_")+" ",\ "failed streak frequent value check".replace(" ","_")+" ",\ "failed check on length of multiday period".replace(" ","_")+" ",\ "failed megaconsistency check".replace(" ","_")+" ",\ "failed naught check".replace(" ","_")+" ",\ "failed climatological outlier check".replace(" ","_")+" ",\ "failed lagged range check".replace(" ","_")+" ",\ "failed spatial consistency check".replace(" ","_")+" ",\ "failed temporal consistency check".replace(" ","_")+" ",\ "failed bounds check".replace(" ","_")+" ",\ "failed climatological outlier check".replace(" ","_")+" ",\ "flagged as a result of an official Datzilla investigation".replace(" ","_")],\ dtype='str') # Source Flag (SRCFLAG) srcflag = 2 srcflag_codes = np.array([ord(x) for x in ["0","6","7","A","a","B","b","C","E","F","G","H","I","K","M","N","Q","R","r","S","s",\ "T","U","u","W","X","Z","z"]],dtype='b') srcflag_meanings = np.array(["US Cooperative Summary of the Day".replace(" ","_")+" ",\ "CDMP Cooperative Summary of the Day".replace(" ","_")+" ",\ "US Cooperative Summary of the Day Transmitted via WxCoder3".replace(" ","_")+" ",\ "Automated Surface Observing System real time data since January 1 2006".replace(" ","_")+" ",\ "Australian data from the Australian Bureau of Meteorology".replace(" ","_")+" ",\ "US ASOS data for October 2000 to December 2005".replace(" ","_")+" ",\ "Belarus update".replace(" ","_")+" ",\ "Environment Canada".replace(" ","_")+" ",\ "European Climate Assessment and Dataset".replace(" ","_")+" ",\ "US Fort data".replace(" ","_")+" ",\ "Official Global Climate Observing System".replace(" ","_")+" ",\ "High Plains Regional Climate Center real time data".replace(" ","_")+" ",\ "International collection non U.S. data received through personal contacts".replace(" ","_")+" ",\ "US Cooperative Summary of the Day data digitized from paper observer forms".replace(" ","_")+" ",\ "Monthly METAR Extract".replace(" ","_")+" ",\ "Community Collaborative Rain Hail and Snow".replace(" ","_")+" ",\ "Data from several African countries that had been quarantined".replace(" ","_")+" ",\ "Climate Reference Network and Historical Climatology Network Modernized".replace(" ","_")+" ",\ "All Russian Research Institute of Hydrometeorological Information World Data Center".replace(" ","_")+" ",\ "Global Summary of the Day".replace(" ","_")+" ",\ "China Meteorological Administration National Meteorological Information Center".replace(" ","_")+" ",\ "SNOwpack TELemtry data obtained from the Western Regional Climate Center".replace(" ","_")+" ",\ "Remote Automatic Weather Station data obtained from the Western Regional Climate Center".replace(" ","_")+" ",\ "Ukraine update".replace(" ","_")+" ",\ "WBAN ASOS Summary of the Day from Integrated Surface Data ISD".replace(" ","_")+" ",\ "US First Order Summary of the Day".replace(" ","_")+" ",\ "Datzilla official additions or replacements".replace(" ","_")+" ",\ "Uzbekistan update ".replace(" ","_")],\ dtype='str') # Get Version Number of GHCN-D ghcnd_version = gp.get_ghcnd_version() # Grab Data gp.get_data_station(station_id) # Read in GHCN-D Data infile = station_id + ".dly" file_handle = open(infile, 'r') ghcnd_contents = file_handle.readlines() file_handle.close() # Get Year Start and End of File for time dimensions station_start_year = int(ghcnd_contents[0][11:15]) station_end_year = int(ghcnd_contents[len(ghcnd_contents) - 1][11:15]) station_start_month = int(ghcnd_contents[0][15:17]) station_end_month = int(ghcnd_contents[len(ghcnd_contents) - 1][15:17]) num_values = 0 results_time = np.zeros((num_years * 12 * 31), dtype='f') - (9999.0) results_pos = np.zeros((num_years, 12, 31), dtype='f') - (9999.0) for year in xrange(station_start_year, station_end_year + 1): year_counter = int(year - station_start_year) if year == station_start_year: begin_month = int(station_start_month - 1) else: begin_month = 0 if year == station_end_year: end_month = int(station_end_month) else: end_month = 12 for month_counter in xrange(begin_month, end_month): month = month_counter + 1 for day_counter in xrange(0, 31): day = day_counter + 1 try: current_date = date(year, month, day) num_days = (current_date - start_date).days results_time[num_values] = num_days results_pos[year_counter, month_counter, day_counter] = int(num_values) num_values += 1 except: pass ################################################# # Open netCDF file outfile = station_id + '.nc' test = os.path.exists(outfile) if test == True: os.remove(outfile) output = nc.Dataset(outfile, mode='w') ################################################# # Create global attributes output.title = "Global Historical Climatology Network - Daily Dataset" output.summary = "GHCN-Daily is an integrated database of daily climate summaries from land surface stations across the globe. "+\ "GHCN-Daily is comprised of daily climate records from numerous sources that have been integrated and "+\ "subjected to a common suite of quality assurance reviews. This dataset includes the top five core elements: "+\ "PRCP (precipitation), SNOW (snowfall), SNWD (snow depth), TMAX (maximum temperature), TMIN (minimum temperature)" output.version = ghcnd_version output.keywords = "daily, station, extremes, temperature, precipitation, snowfall, snow depth" output.Conventions = "CF-1.6, ACDD-1.3" output.institution = "Cooperative Institute for Climate and Satellites - North Carolina (CICS-NC) and "+\ "NOAAs National Centers for Environmental Information (NCEI), Asheville, North Carolina, USA" output.source = "surface observations from multiple sources around the globe" output.featureType = "timeSeries" output.history = "File generatred on ", str(datetime.datetime.now()) output.creator_name = "Jared Rennie, CICS-NC" output.creator_email = "*****@*****.**" output.creator_url = "http://www.cicsnc.org/people/jared-rennie/" output.references = "Menne et al 2012: http://dx.doi.org/10.1175/JTECH-D-11-00103.1" output.comment = "More information can be found here: ftp://ftp.ncdc.noaa.gov/pub/data/ghcn/daily/readme.txt" ################################################# # Create Dimensions output.createDimension('element', num_elements) output.createDimension('time', num_values) output.createDimension('name_strlen', 30) output.createDimension('id_strlen', 11) ################################################# # Create Variables # LON lon_var = output.createVariable('lon', datatype='f') lon_var.standard_name = "longitude" lon_var.long_name = "station longitude" lon_var.units = "degrees_east" # LAT lat_var = output.createVariable('lat', datatype='f') lat_var.standard_name = "latitude" lat_var.long_name = "station latitude" lat_var.units = "degrees_north" # ELEV (ALT) alt_var = output.createVariable('alt', datatype='f') alt_var.long_name = "vertical distance above the surface" alt_var.standard_name = "height" alt_var.units = "m" alt_var.positive = "up" alt_var.axis = "Z" # ID id_var = output.createVariable('id', datatype='S1', dimensions=('id_strlen')) id_var.long_name = "station identifier" # NAME name_var = output.createVariable('station_name', datatype='S1', dimensions=('name_strlen')) name_var.long_name = "station name" name_var.cf_role = "timeseries_id" # TIME time_var = output.createVariable('time', datatype='f8', dimensions='time') time_var.standard_name = "time" time_var.long_name = "Time of Measurement" time_var.units = "days since ", begin_year, "-01-01 00:00:00" time_var.calendar = "gregorian" time_var.axis = "T" time_var[:] = results_time[0:num_values] time_var.valid_min = np.min(results_time[0:num_values]) # FLAGS mflag_var = output.createVariable('mflag', datatype='b', dimensions=('time', 'element'), fill_value=32.) mflag_var.long_name = "measurement flag" mflag_var.flag_values = mflag_codes mflag_var.flag_meanings = mflag_meanings qcflag_var = output.createVariable('qcflag', datatype='b', dimensions=('time', 'element'), fill_value=32.) qcflag_var.long_name = "quality control flag" qcflag_var.flag_values = qcflag_codes qcflag_var.flag_meanings = qcflag_meanings srcflag_var = output.createVariable('srcflag', datatype='b', dimensions=('time', 'element'), fill_value=32.) srcflag_var.long_name = "source flag" srcflag_var.flag_values = srcflag_codes srcflag_var.flag_meanings = srcflag_meanings # TMAX tmax_var = output.createVariable('tmax', datatype='f', dimensions=('time'), fill_value=-9999.) tmax_var.long_name = "surface maximum temperature" tmax_var.units = "Celsius" tmax_var.coordinates = "time lat lon alt station_name" tmax_var.ancillary_variables = "mflag qcflag srcflag" # TMIN tmin_var = output.createVariable('tmin', datatype='f', dimensions=('time'), fill_value=-9999.) tmin_var.long_name = "surface minimum temperature" tmin_var.units = "Celsius" tmin_var.coordinates = "time lat lon alt station_name" tmin_var.ancillary_variables = "mflag qcflag srcflag" # PRCP prcp_var = output.createVariable('prcp', datatype='f', dimensions=('time'), fill_value=-9999.) prcp_var.long_name = "surface precipitation" prcp_var.units = "mm" prcp_var.coordinates = "time lat lon alt station_name" prcp_var.ancillary_variables = "mflag qcflag srcflag" # SNOW snow_var = output.createVariable('snow', datatype='f', dimensions=('time'), fill_value=-9999.) snow_var.long_name = "surface snowfall" snow_var.units = "mm" snow_var.coordinates = "time lat lon alt station_name" snow_var.ancillary_variables = "mflag qcflag srcflag" # SNWD snwd_var = output.createVariable('snwd', datatype='f', dimensions=('time'), fill_value=-9999.) snwd_var.long_name = "surface snow depth" snwd_var.units = "mm" snwd_var.coordinates = "time lat lon alt station_name" snwd_var.ancillary_variables = "mflag qcflag srcflag" ################################################# # Read in GHCN-D Meta ghcnd_stations = gp.get_ghcnd_stations() ghcnd_meta = ghcnd_stations[ghcnd_stations[:, 0] == station_id] ghcnd_id = ghcnd_meta[0][0] ghcnd_lat = float(ghcnd_meta[0][1]) ghcnd_lon = float(ghcnd_meta[0][2]) ghcnd_alt = float(ghcnd_meta[0][3]) ghcnd_name = ghcnd_meta[0][5] ghcnd_name = ghcnd_name.strip() ghcnd_name = re.sub(' +', ' ', ghcnd_name) ghcnd_name = ghcnd_name.replace(" ", "_") for string_counter in xrange(0, len(ghcnd_id)): id_var[string_counter] = ghcnd_id[string_counter] lat_var[:] = ghcnd_lat lon_var[:] = ghcnd_lon alt_var[:] = ghcnd_alt for string_counter in xrange(0, len(ghcnd_name)): name_var[string_counter] = ghcnd_name[string_counter] ################################################# # Go through GHCN-D Data ghcnd_data = np.zeros((num_values, num_elements), dtype='f') - (9999.0) ghcnd_flag = np.zeros( (num_values, num_elements, num_flags), dtype='i') + 32 for counter in xrange(len(ghcnd_contents)): element = ghcnd_contents[counter][17:21] if element == "TMAX" or element == "TMIN" or element == "PRCP" or element == "SNOW" or element == "SNWD": if element == "TMAX": element_counter = tmax divisor = 10.0 if element == "TMIN": element_counter = tmin divisor = 10.0 if element == "PRCP": element_counter = prcp divisor = 10.0 if element == "SNOW": element_counter = snow divisor = 1.0 if element == "SNWD": element_counter = snwd divisor = 1.0 year = int(ghcnd_contents[counter][11:15]) year_counter = int(year - station_start_year) month = int(ghcnd_contents[counter][15:17]) month_counter = int(month - 1) char = 21 for day_counter in xrange(0, 31): time_pos = results_pos[year_counter, month_counter, day_counter] # Get Values / Flags if ghcnd_contents[counter][char:char + 5] != "-9999": ghcnd_data[time_pos, element_counter] = float( ghcnd_contents[counter][char:char + 5]) / divisor ghcnd_flag[time_pos, element_counter, mflag] = ord( ghcnd_contents[counter][char + 5:char + 6]) ghcnd_flag[time_pos, element_counter, qcflag] = ord( ghcnd_contents[counter][char + 6:char + 7]) ghcnd_flag[time_pos, element_counter, srcflag] = ord( ghcnd_contents[counter][char + 7:char + 8]) char = char + 8 ################################################# # Assign data to netCDF variables tmax_var[:] = ghcnd_data[:, tmax] tmax_var.valid_min = np.min( np.ma.masked_equal( np.ma.masked_where(ghcnd_flag[:, tmax, qcflag] != ord(" "), ghcnd_data[:, tmax]), -9999)) tmax_var.valid_max = np.max( np.ma.masked_equal( np.ma.masked_where(ghcnd_flag[:, tmax, qcflag] != ord(" "), ghcnd_data[:, tmax]), -9999)) tmin_var[:] = ghcnd_data[:, tmin] tmin_var.valid_min = np.min( np.ma.masked_equal( np.ma.masked_where(ghcnd_flag[:, tmin, qcflag] != ord(" "), ghcnd_data[:, tmin]), -9999)) tmin_var.valid_max = np.max( np.ma.masked_equal( np.ma.masked_where(ghcnd_flag[:, tmin, qcflag] != ord(" "), ghcnd_data[:, tmin]), -9999)) prcp_var[:] = ghcnd_data[:, prcp] prcp_var.valid_min = np.min( np.ma.masked_equal( np.ma.masked_where(ghcnd_flag[:, prcp, qcflag] != ord(" "), ghcnd_data[:, prcp]), -9999)) prcp_var.valid_max = np.max( np.ma.masked_equal( np.ma.masked_where(ghcnd_flag[:, prcp, qcflag] != ord(" "), ghcnd_data[:, prcp]), -9999)) snow_var[:] = ghcnd_data[:, snow] snow_var.valid_min = np.min( np.ma.masked_equal( np.ma.masked_where(ghcnd_flag[:, snow, qcflag] != ord(" "), ghcnd_data[:, snow]), -9999)) snow_var.valid_max = np.max( np.ma.masked_equal( np.ma.masked_where(ghcnd_flag[:, snow, qcflag] != ord(" "), ghcnd_data[:, snow]), -9999)) snwd_var[:] = ghcnd_data[:, snwd] snwd_var.valid_min = np.min( np.ma.masked_equal( np.ma.masked_where(ghcnd_flag[:, snwd, qcflag] != ord(" "), ghcnd_data[:, snwd]), -9999)) snwd_var.valid_max = np.max( np.ma.masked_equal( np.ma.masked_where(ghcnd_flag[:, snwd, qcflag] != ord(" "), ghcnd_data[:, snwd]), -9999)) mflag_var[:, :] = ghcnd_flag[:, :, mflag] qcflag_var[:, :] = ghcnd_flag[:, :, qcflag] srcflag_var[:, :] = ghcnd_flag[:, :, srcflag] ################################################# # Close netCDF file output.close() return None
def get_metadata(station_id): # Get Metadata info from station Inventory file ghcnd_stations = gp.get_ghcnd_stations() ghcnd_meta = ghcnd_stations[ghcnd_stations[:, 0] == station_id] ghcnd_name = "N/A" ghcnd_lat = "N/A" ghcnd_lon = "N/A" ghcnd_alt = "N/A" ghcnd_id = ghcnd_meta[0][0] ghcnd_lat = float(ghcnd_meta[0][1]) ghcnd_lon = float(ghcnd_meta[0][2]) ghcnd_alt = float(ghcnd_meta[0][3]) ghcnd_name = ghcnd_meta[0][5] ghcnd_name = ghcnd_name.strip() ghcnd_name = re.sub(' +', ' ', ghcnd_name) ghcnd_name = ghcnd_name.replace(" ", "_") # Get Metadata info from HOMR homr_link = 'http://www.ncdc.noaa.gov/homr/services/station/search?qid=GHCND:' + station_id ghcnd_state = "N/A" ghcnd_climdiv = "N/A" ghcnd_county = "N/A" ghcnd_nwswfo = "N/A" ghcnd_coopid = "N/A" ghcnd_wbanid = "N/A" try: homr = r.get(homr_link) homr_json = json.loads(homr.text) except: pass # Get State Station is in (HOMR) try: ghcnd_state = json.dumps( homr_json['stationCollection']['stations'][0]['location'] ['nwsInfo']['climateDivisions'][0]['stateProvince']) except: pass # Get Climate Division Station is in (HOMR) try: ghcnd_climdiv = json.dumps( homr_json['stationCollection']['stations'][0]['location'] ['nwsInfo']['climateDivisions'][0]['climateDivision']) except: pass # Get County Station is in (HOMR) try: ghcnd_county = json.dumps( homr_json['stationCollection']['stations'][0]['location'] ['geoInfo']['counties'][0]['county']) ghcnd_county = ghcnd_county.replace(" ", "_") except: pass # Get NWS WFO station is in (HOMR) try: ghcnd_nwswfo = json.dumps( homr_json['stationCollection']['stations'][0]['location'] ['nwsInfo']['nwsWfos'][0]['nwsWfo']) except: pass # Get COOP ID if exists (HOMR) has_coop = False has_wban = False try: identifiers = homr_json['stationCollection']['stations'][0][ 'identifiers'] for counter in range(0, 10): for key, value in homr_json['stationCollection']['stations'][0][ 'identifiers'][counter].iteritems(): if key == "idType" and homr_json['stationCollection'][ 'stations'][0]['identifiers'][counter][key] == "COOP": has_coop = True if key == "idType" and homr_json['stationCollection'][ 'stations'][0]['identifiers'][counter][key] == "WBAN": has_wban = True if key == "id" and has_coop: ghcnd_coopid = homr_json['stationCollection']['stations'][ 0]['identifiers'][counter][key] has_coop = False if key == "id" and has_wban: ghcnd_wbanid = homr_json['stationCollection']['stations'][ 0]['identifiers'][counter][key] has_wban = False except: pass # Write everything out print(station_id) print(" Station Name: ", ghcnd_name) print(" Station Lat: ", ghcnd_lat) print(" Station Lon: ", ghcnd_lon) print(" Station Elev: ", ghcnd_alt) print(" Station State: ", ghcnd_state.strip('""')) print(" Station Climate Division: ", ghcnd_climdiv.strip('""')) print(" Station County: ", ghcnd_county.strip('""')) print(" Station NWS Office: ", ghcnd_nwswfo.strip('""')) print(" Station COOP ID: ", ghcnd_coopid.strip('""')) print(" Station WBAN ID: ", ghcnd_wbanid.strip('""')) return None
def get_metadata(station_id): # Get Metadata info from station Inventory file ghcnd_stations=gp.get_ghcnd_stations() ghcnd_meta = ghcnd_stations[ghcnd_stations[:,0] == station_id] ghcnd_name="N/A" ghcnd_lat="N/A" ghcnd_lon="N/A" ghcnd_alt="N/A" ghcnd_id=ghcnd_meta[0][0] ghcnd_lat=float(ghcnd_meta[0][1]) ghcnd_lon=float(ghcnd_meta[0][2]) ghcnd_alt=float(ghcnd_meta[0][3]) ghcnd_name=ghcnd_meta[0][5] ghcnd_name = ghcnd_name.strip() ghcnd_name = re.sub(' +',' ',ghcnd_name) ghcnd_name = ghcnd_name.replace(" ","_") # Get Metadata info from HOMR homr_link='http://www.ncdc.noaa.gov/homr/services/station/search?qid=GHCND:'+station_id ghcnd_state="N/A" ghcnd_climdiv="N/A" ghcnd_county="N/A" ghcnd_nwswfo="N/A" ghcnd_coopid="N/A" ghcnd_wbanid="N/A" try: homr=r.get(homr_link) homr_json=json.loads(homr.text) except: pass # Get State Station is in (HOMR) try: ghcnd_state=json.dumps(homr_json['stationCollection']['stations'][0]['location']['nwsInfo']['climateDivisions'][0]['stateProvince']) except: pass # Get Climate Division Station is in (HOMR) try: ghcnd_climdiv=json.dumps(homr_json['stationCollection']['stations'][0]['location']['nwsInfo']['climateDivisions'][0]['climateDivision']) except: pass # Get County Station is in (HOMR) try: ghcnd_county=json.dumps(homr_json['stationCollection']['stations'][0]['location']['geoInfo']['counties'][0]['county']) ghcnd_county=ghcnd_county.replace(" ","_") except: pass # Get NWS WFO station is in (HOMR) try: ghcnd_nwswfo=json.dumps(homr_json['stationCollection']['stations'][0]['location']['nwsInfo']['nwsWfos'][0]['nwsWfo']) except: pass # Get COOP ID if exists (HOMR) has_coop=False has_wban=False try: identifiers=homr_json['stationCollection']['stations'][0]['identifiers'] for counter in xrange(0,10): for key, value in homr_json['stationCollection']['stations'][0]['identifiers'][counter].iteritems(): if key == "idType" and homr_json['stationCollection']['stations'][0]['identifiers'][counter][key] == "COOP": has_coop=True if key == "idType" and homr_json['stationCollection']['stations'][0]['identifiers'][counter][key] == "WBAN": has_wban=True if key == "id" and has_coop: ghcnd_coopid=homr_json['stationCollection']['stations'][0]['identifiers'][counter][key] has_coop=False if key == "id" and has_wban: ghcnd_wbanid=homr_json['stationCollection']['stations'][0]['identifiers'][counter][key] has_wban=False except: pass # Write everything out print(station_id) print(" Station Name: ",ghcnd_name) print(" Station Lat: ",ghcnd_lat) print(" Station Lon: ",ghcnd_lon) print(" Station Elev: ",ghcnd_alt) print(" Station State: ",ghcnd_state.strip('""')) print(" Station Climate Division: ",ghcnd_climdiv.strip('""')) print(" Station County: ",ghcnd_county.strip('""')) print(" Station NWS Office: ",ghcnd_nwswfo.strip('""')) print(" Station COOP ID: ",ghcnd_coopid.strip('""')) print(" Station WBAN ID: ",ghcnd_wbanid.strip('""')) return None
def output_to_netcdf(station_id): print("\nOUTPUTTING TO netCDF: ",station_id,".nc") begin_year=1700 end_year=datetime.datetime.now().year num_years=(end_year-begin_year) + 1 start_date=date(begin_year, 1, 1) end_date=date(end_year,12,31) # 5 Elements of GHCN-D num_elements=5 tmax=0 tmin=1 prcp=2 snow=3 snwd=4 # 3 Flags for each value num_flags=3 # Measurement Flag (MFLAG) mflag=0 mflag_codes = np.array([ord(x) for x in ["B","D","H","K","L","O","P","T","W"]],dtype='b') mflag_meanings = np.array(["precipitation total formed from two 12 hour totals".replace(" ","_")+" ",\ "precipitation total formed from four six hour totals".replace(" ","_")+" ",\ "represents highest or lowest hourly temperature".replace(" ","_")+" ",\ "converted from knots".replace(" ","_")+" ",\ "temperature appears to be lagged with respect to reported hour of observation".replace(" ","_")+" ",\ "converted from oktas".replace(" ","_")+" ",\ "identified as missing presumed zero in DSI 3200 and 3206".replace(" ","_")+" ",\ "trace of precipitation snowfall or snow depth".replace(" ","_")+" ",\ "converted from 16 point WBAN code for wind direction".replace(" ","_")],\ dtype='str') # Quality Control Flag (QCFLAG) qcflag=1 qcflag_codes = np.array([ord(x) for x in ["D","G","I","K","L","M","N","O","R","S","T","W","X","Z"]],dtype='b') qcflag_meanings = np.array(["failed duplicate check".replace(" ","_")+" ",\ "failed gap check".replace(" ","_")+" ",\ "failed internal consistency check".replace(" ","_")+" ",\ "failed streak frequent value check".replace(" ","_")+" ",\ "failed check on length of multiday period".replace(" ","_")+" ",\ "failed megaconsistency check".replace(" ","_")+" ",\ "failed naught check".replace(" ","_")+" ",\ "failed climatological outlier check".replace(" ","_")+" ",\ "failed lagged range check".replace(" ","_")+" ",\ "failed spatial consistency check".replace(" ","_")+" ",\ "failed temporal consistency check".replace(" ","_")+" ",\ "failed bounds check".replace(" ","_")+" ",\ "failed climatological outlier check".replace(" ","_")+" ",\ "flagged as a result of an official Datzilla investigation".replace(" ","_")],\ dtype='str') # Source Flag (SRCFLAG) srcflag=2 srcflag_codes = np.array([ord(x) for x in ["0","6","7","A","a","B","b","C","E","F","G","H","I","K","M","N","Q","R","r","S","s",\ "T","U","u","W","X","Z","z"]],dtype='b') srcflag_meanings = np.array(["US Cooperative Summary of the Day".replace(" ","_")+" ",\ "CDMP Cooperative Summary of the Day".replace(" ","_")+" ",\ "US Cooperative Summary of the Day Transmitted via WxCoder3".replace(" ","_")+" ",\ "Automated Surface Observing System real time data since January 1 2006".replace(" ","_")+" ",\ "Australian data from the Australian Bureau of Meteorology".replace(" ","_")+" ",\ "US ASOS data for October 2000 to December 2005".replace(" ","_")+" ",\ "Belarus update".replace(" ","_")+" ",\ "Environment Canada".replace(" ","_")+" ",\ "European Climate Assessment and Dataset".replace(" ","_")+" ",\ "US Fort data".replace(" ","_")+" ",\ "Official Global Climate Observing System".replace(" ","_")+" ",\ "High Plains Regional Climate Center real time data".replace(" ","_")+" ",\ "International collection non U.S. data received through personal contacts".replace(" ","_")+" ",\ "US Cooperative Summary of the Day data digitized from paper observer forms".replace(" ","_")+" ",\ "Monthly METAR Extract".replace(" ","_")+" ",\ "Community Collaborative Rain Hail and Snow".replace(" ","_")+" ",\ "Data from several African countries that had been quarantined".replace(" ","_")+" ",\ "Climate Reference Network and Historical Climatology Network Modernized".replace(" ","_")+" ",\ "All Russian Research Institute of Hydrometeorological Information World Data Center".replace(" ","_")+" ",\ "Global Summary of the Day".replace(" ","_")+" ",\ "China Meteorological Administration National Meteorological Information Center".replace(" ","_")+" ",\ "SNOwpack TELemtry data obtained from the Western Regional Climate Center".replace(" ","_")+" ",\ "Remote Automatic Weather Station data obtained from the Western Regional Climate Center".replace(" ","_")+" ",\ "Ukraine update".replace(" ","_")+" ",\ "WBAN ASOS Summary of the Day from Integrated Surface Data ISD".replace(" ","_")+" ",\ "US First Order Summary of the Day".replace(" ","_")+" ",\ "Datzilla official additions or replacements".replace(" ","_")+" ",\ "Uzbekistan update ".replace(" ","_")],\ dtype='str') # Get Version Number of GHCN-D ghcnd_version=gp.get_ghcnd_version() # Grab Data gp.get_data_station(station_id) # Read in GHCN-D Data infile = station_id+".dly" file_handle = open(infile, 'r') ghcnd_contents = file_handle.readlines() file_handle.close() # Get Year Start and End of File for time dimensions station_start_year = int(ghcnd_contents[0][11:15]) station_end_year = int(ghcnd_contents[len(ghcnd_contents)-1][11:15]) station_start_month = int(ghcnd_contents[0][15:17]) station_end_month = int(ghcnd_contents[len(ghcnd_contents)-1][15:17]) num_values=0 results_time = np.zeros((num_years*12*31),dtype='f')-(9999.0) results_pos = np.zeros((num_years,12,31),dtype='f')-(9999.0) for year in xrange(station_start_year,station_end_year+1): year_counter = int(year - station_start_year) if year == station_start_year: begin_month = int(station_start_month-1) else: begin_month = 0 if year == station_end_year: end_month = int(station_end_month) else: end_month = 12 for month_counter in xrange(begin_month,end_month): month = month_counter + 1 for day_counter in xrange(0,31): day = day_counter + 1 try: current_date=date(year,month,day) num_days = (current_date-start_date).days results_time[num_values] = num_days results_pos[year_counter,month_counter,day_counter] = int(num_values) num_values+=1 except: pass ################################################# # Open netCDF file outfile=station_id+'.nc' test=os.path.exists(outfile) if test == True: os.remove(outfile) output = nc.Dataset(outfile, mode='w') ################################################# # Create global attributes output.title = "Global Historical Climatology Network - Daily Dataset" output.summary = "GHCN-Daily is an integrated database of daily climate summaries from land surface stations across the globe. "+\ "GHCN-Daily is comprised of daily climate records from numerous sources that have been integrated and "+\ "subjected to a common suite of quality assurance reviews. This dataset includes the top five core elements: "+\ "PRCP (precipitation), SNOW (snowfall), SNWD (snow depth), TMAX (maximum temperature), TMIN (minimum temperature)" output.version=ghcnd_version output.keywords = "daily, station, extremes, temperature, precipitation, snowfall, snow depth" output.Conventions = "CF-1.6, ACDD-1.3" output.institution = "Cooperative Institute for Climate and Satellites - North Carolina (CICS-NC) and "+\ "NOAAs National Centers for Environmental Information (NCEI), Asheville, North Carolina, USA" output.source = "surface observations from multiple sources around the globe" output.featureType = "timeSeries" output.history = "File generatred on ",str(datetime.datetime.now()) output.creator_name = "Jared Rennie, CICS-NC" output.creator_email = "*****@*****.**" output.creator_url = "http://www.cicsnc.org/people/jared-rennie/" output.references= "Menne et al 2012: http://dx.doi.org/10.1175/JTECH-D-11-00103.1" output.comment="More information can be found here: ftp://ftp.ncdc.noaa.gov/pub/data/ghcn/daily/readme.txt" ################################################# # Create Dimensions output.createDimension('element',num_elements) output.createDimension('time',num_values) output.createDimension('name_strlen',30) output.createDimension('id_strlen',11) ################################################# # Create Variables # LON lon_var = output.createVariable('lon', datatype='f') lon_var.standard_name = "longitude" lon_var.long_name = "station longitude" lon_var.units = "degrees_east" # LAT lat_var = output.createVariable('lat', datatype='f') lat_var.standard_name = "latitude" lat_var.long_name = "station latitude" lat_var.units = "degrees_north" # ELEV (ALT) alt_var = output.createVariable('alt', datatype='f') alt_var.long_name = "vertical distance above the surface" alt_var.standard_name = "height" alt_var.units = "m" alt_var.positive = "up" alt_var.axis = "Z" # ID id_var = output.createVariable('id', datatype='S1', dimensions=('id_strlen')) id_var.long_name = "station identifier" # NAME name_var = output.createVariable('station_name', datatype='S1', dimensions=('name_strlen')) name_var.long_name = "station name" name_var.cf_role = "timeseries_id" # TIME time_var = output.createVariable('time', datatype='f8', dimensions='time') time_var.standard_name = "time" time_var.long_name = "Time of Measurement" time_var.units = "days since ",begin_year,"-01-01 00:00:00" time_var.calendar = "gregorian" time_var.axis = "T" time_var[:] = results_time[0:num_values] time_var.valid_min = np.min(results_time[0:num_values]) # FLAGS mflag_var = output.createVariable('mflag', datatype='b', dimensions=('time','element'), fill_value=32.) mflag_var.long_name = "measurement flag" mflag_var.flag_values=mflag_codes mflag_var.flag_meanings=mflag_meanings qcflag_var = output.createVariable('qcflag', datatype='b', dimensions=('time','element'), fill_value=32.) qcflag_var.long_name = "quality control flag" qcflag_var.flag_values=qcflag_codes qcflag_var.flag_meanings=qcflag_meanings srcflag_var = output.createVariable('srcflag', datatype='b', dimensions=('time','element'), fill_value=32.) srcflag_var.long_name = "source flag" srcflag_var.flag_values=srcflag_codes srcflag_var.flag_meanings=srcflag_meanings # TMAX tmax_var = output.createVariable('tmax', datatype='f', dimensions=('time'), fill_value=-9999.) tmax_var.long_name = "surface maximum temperature" tmax_var.units = "Celsius" tmax_var.coordinates = "time lat lon alt station_name" tmax_var.ancillary_variables = "mflag qcflag srcflag" # TMIN tmin_var = output.createVariable('tmin', datatype='f', dimensions=('time'), fill_value=-9999.) tmin_var.long_name = "surface minimum temperature" tmin_var.units = "Celsius" tmin_var.coordinates = "time lat lon alt station_name" tmin_var.ancillary_variables = "mflag qcflag srcflag" # PRCP prcp_var = output.createVariable('prcp', datatype='f', dimensions=('time'), fill_value=-9999.) prcp_var.long_name = "surface precipitation" prcp_var.units = "mm" prcp_var.coordinates = "time lat lon alt station_name" prcp_var.ancillary_variables = "mflag qcflag srcflag" # SNOW snow_var = output.createVariable('snow', datatype='f', dimensions=('time'), fill_value=-9999.) snow_var.long_name = "surface snowfall" snow_var.units = "mm" snow_var.coordinates = "time lat lon alt station_name" snow_var.ancillary_variables = "mflag qcflag srcflag" # SNWD snwd_var = output.createVariable('snwd', datatype='f', dimensions=('time'), fill_value=-9999.) snwd_var.long_name = "surface snow depth" snwd_var.units = "mm" snwd_var.coordinates = "time lat lon alt station_name" snwd_var.ancillary_variables = "mflag qcflag srcflag" ################################################# # Read in GHCN-D Meta ghcnd_stations=gp.get_ghcnd_stations() ghcnd_meta = ghcnd_stations[ghcnd_stations[:,0] == station_id] ghcnd_id=ghcnd_meta[0][0] ghcnd_lat=float(ghcnd_meta[0][1]) ghcnd_lon=float(ghcnd_meta[0][2]) ghcnd_alt=float(ghcnd_meta[0][3]) ghcnd_name=ghcnd_meta[0][5] ghcnd_name = ghcnd_name.strip() ghcnd_name = re.sub(' +',' ',ghcnd_name) ghcnd_name = ghcnd_name.replace(" ","_") for string_counter in xrange(0,len(ghcnd_id)): id_var[string_counter] = ghcnd_id[string_counter] lat_var[:] = ghcnd_lat lon_var[:] = ghcnd_lon alt_var[:] = ghcnd_alt for string_counter in xrange(0,len(ghcnd_name)): name_var[string_counter] = ghcnd_name[string_counter] ################################################# # Go through GHCN-D Data ghcnd_data= np.zeros((num_values,num_elements),dtype='f')-(9999.0) ghcnd_flag= np.zeros((num_values,num_elements,num_flags),dtype='i')+32 for counter in xrange(len(ghcnd_contents)): element = ghcnd_contents[counter][17:21] if element == "TMAX" or element == "TMIN" or element == "PRCP" or element == "SNOW" or element == "SNWD": if element == "TMAX": element_counter=tmax divisor = 10.0 if element == "TMIN": element_counter=tmin divisor = 10.0 if element == "PRCP": element_counter=prcp divisor = 10.0 if element == "SNOW": element_counter=snow divisor = 1.0 if element == "SNWD": element_counter=snwd divisor = 1.0 year = int(ghcnd_contents[counter][11:15]) year_counter = int(year - station_start_year) month = int(ghcnd_contents[counter][15:17]) month_counter = int(month - 1) char=21 for day_counter in xrange(0,31): time_pos=results_pos[year_counter,month_counter,day_counter] # Get Values / Flags if ghcnd_contents[counter][char:char+5] != "-9999": ghcnd_data[time_pos,element_counter] = float(ghcnd_contents[counter][char:char+5]) / divisor ghcnd_flag[time_pos,element_counter,mflag] = ord(ghcnd_contents[counter][char+5:char+6]) ghcnd_flag[time_pos,element_counter,qcflag] = ord(ghcnd_contents[counter][char+6:char+7]) ghcnd_flag[time_pos,element_counter,srcflag] = ord(ghcnd_contents[counter][char+7:char+8]) char = char + 8 ################################################# # Assign data to netCDF variables tmax_var[:] = ghcnd_data[:,tmax] tmax_var.valid_min = np.min(np.ma.masked_equal(np.ma.masked_where(ghcnd_flag[:,tmax,qcflag]!=ord(" "),ghcnd_data[:,tmax]),-9999)) tmax_var.valid_max = np.max(np.ma.masked_equal(np.ma.masked_where(ghcnd_flag[:,tmax,qcflag]!=ord(" "),ghcnd_data[:,tmax]),-9999)) tmin_var[:] = ghcnd_data[:,tmin] tmin_var.valid_min = np.min(np.ma.masked_equal(np.ma.masked_where(ghcnd_flag[:,tmin,qcflag]!=ord(" "),ghcnd_data[:,tmin]),-9999)) tmin_var.valid_max = np.max(np.ma.masked_equal(np.ma.masked_where(ghcnd_flag[:,tmin,qcflag]!=ord(" "),ghcnd_data[:,tmin]),-9999)) prcp_var[:] = ghcnd_data[:,prcp] prcp_var.valid_min = np.min(np.ma.masked_equal(np.ma.masked_where(ghcnd_flag[:,prcp,qcflag]!=ord(" "),ghcnd_data[:,prcp]),-9999)) prcp_var.valid_max = np.max(np.ma.masked_equal(np.ma.masked_where(ghcnd_flag[:,prcp,qcflag]!=ord(" "),ghcnd_data[:,prcp]),-9999)) snow_var[:] = ghcnd_data[:,snow] snow_var.valid_min = np.min(np.ma.masked_equal(np.ma.masked_where(ghcnd_flag[:,snow,qcflag]!=ord(" "),ghcnd_data[:,snow]),-9999)) snow_var.valid_max = np.max(np.ma.masked_equal(np.ma.masked_where(ghcnd_flag[:,snow,qcflag]!=ord(" "),ghcnd_data[:,snow]),-9999)) snwd_var[:] = ghcnd_data[:,snwd] snwd_var.valid_min = np.min(np.ma.masked_equal(np.ma.masked_where(ghcnd_flag[:,snwd,qcflag]!=ord(" "),ghcnd_data[:,snwd]),-9999)) snwd_var.valid_max = np.max(np.ma.masked_equal(np.ma.masked_where(ghcnd_flag[:,snwd,qcflag]!=ord(" "),ghcnd_data[:,snwd]),-9999)) mflag_var[:,:] = ghcnd_flag[:,:,mflag] qcflag_var[:,:] = ghcnd_flag[:,:,qcflag] srcflag_var[:,:] = ghcnd_flag[:,:,srcflag] ################################################# # Close netCDF file output.close() return None
def plot_snowfall(station_id): print("\nPLOTTING SNOWFALL DATA FOR STATION: ",station_id) # Declare Other Variables begin_year=1895 num_elements=1 # SNOW snow=0 num_days=366 end_year=datetime.now().year num_years=(end_year-begin_year) + 1 # Get station metadatafile ghcnd_stations=gp.get_ghcnd_stations() ghcnd_meta = ghcnd_stations[ghcnd_stations[:,0] == station_id] ghcnd_id=ghcnd_meta[0][0] ghcnd_lat=float(ghcnd_meta[0][1]) ghcnd_lon=float(ghcnd_meta[0][2]) ghcnd_alt=float(ghcnd_meta[0][3]) ghcnd_name=ghcnd_meta[0][5] ghcnd_name = ghcnd_name.strip() ghcnd_name = re.sub(' +',' ',ghcnd_name) ghcnd_name = ghcnd_name.replace(" ","_") # Grab Data gp.get_data_station(station_id) ################################################# # Read in GHCN-D Data (Original, QC'd data removed) infile = station_id+".dly" ghcnd_value = np.zeros((num_years,12,31,num_elements),dtype='f') file_handle = open(infile, 'r') contents = file_handle.readlines() file_handle.close() valid_end=-9999 valid_begin=9999 for counter in xrange(len(contents)): element = contents[counter][17:21] if element == "SNOW": element_counter=snow year = int(contents[counter][11:15]) year_counter = year-begin_year valid_begin=min(valid_begin,year) valid_end=max(valid_end,year) month = int(contents[counter][15:17]) month_counter = month-1 char=21 for day_counter in xrange(0,31): if contents[counter][char:char+5] != "-9999" and contents[counter][char+6:char+7] == " ": ghcnd_value[year_counter][month_counter][day_counter][element_counter] = float(contents[counter][char:char+5]) last_day=day_counter+1 char = char + 8 # Get day of year for last day with valid data last_day=datetime(year, month, last_day).timetuple().tm_yday last_day=last_day+92 # Shift three months if last_day >=365: last_day=last_day-365 # Convert from mm to inch ghcnd_value=(ghcnd_value*0.0393701) # Get Record / Average Values for every day in year average_snow = np.zeros((num_days),dtype='f')-(9999.0) day_of_year=0 day_before=0 for month_counter in [9, 10, 11, 12, 1, 2, 3, 4, 5, 6, 7, 8, 9]: for day_counter in xrange(0,31): try: # Check if leap-year date is valid datetime(year=2012,month=month_counter+1,day=day_counter+1) average_snow[day_of_year] = day_before + ma.average(ghcnd_value[(valid_begin-begin_year):(valid_end-begin_year),month_counter,day_counter,snow]) day_before=average_snow[day_of_year] day_of_year=day_of_year+1 except: pass ################################################# # Create Accumulations new_year_counter=0 snow_accum = np.zeros((num_years+1,num_days),dtype='f') total_accum = np.zeros((num_years+1),dtype='f') for year_counter in xrange(0,num_years): for month_counter in xrange(0,12): if month_counter==9: # Month Begins in Oct new_year_counter=year_counter+1 day_of_year=0 day_before=0 for day_counter in xrange(0,31): try: # Check if date is valid datetime(year=year_counter+begin_year,month=month_counter+1,day=day_counter+1) snow_accum[new_year_counter][day_of_year] = day_before + ghcnd_value[year_counter,month_counter,day_counter,snow] total_accum[new_year_counter]=snow_accum[new_year_counter][day_of_year] day_before=snow_accum[new_year_counter][day_of_year] day_of_year=day_of_year+1 except: pass if month_counter+1==12 and snow_accum[year_counter][365]==0: snow_accum[year_counter][365]=snow_accum[year_counter][364] ################################################# # PLOT # Mask Zero Data before plotting #snow_accum = ma.masked_values(snow_accum, 0.) total_accum = ma.masked_values(total_accum, 0.) #Get Some Stats Needed For Plotting x_axis=range(num_days) x_axis_end=range(last_day) current_loc = num_years-1 current_snow = "%6.2f" % total_accum[current_loc] current_year = current_loc + begin_year current_data=snow_accum[current_loc,0:last_day] current_last=snow_accum[current_loc,last_day] max_snow = "%6.2f" % np.max(total_accum) max_loc = np.argmax(total_accum) max_year = max_loc+begin_year min_snow = "%6.2f" % np.min(total_accum[np.where(total_accum != 0)]) min_loc = np.nanargmin(total_accum) min_year = min_loc+begin_year avg_snow = "%6.2f" % average_snow[365] # Create Figure fig, ax1 = plt.subplots(figsize=(15, 8), edgecolor='white', facecolor='white', dpi=300) # Add grid lines plt.grid(color='black', linestyle='--', linewidth=0.5, alpha=0.3) # Plot Accumulated SNOW (Sort by end of year accumulation and plot by range of color) order=np.argsort(snow_accum[:,364]) color_pos=np.linspace(0.5,1,num_years) order_counter=0 color_counter=0 for year_counter in xrange(0,num_years): pos=order[order_counter] if pos != (num_years-1): plt.plot(x_axis, snow_accum[pos,:], linewidth=0.5, color=colors.rgb2hex(pylab.cm.GnBu(color_pos[color_counter])[0:3])) color_counter=color_counter+1 order_counter=order_counter+1 # Overlay Record Max Snow Year if max_loc==current_loc: plt.plot(x_axis_end, snow_accum[max_loc,0:last_day], color='#084081', linewidth=3, label='Max ('+str(max_year-1)+'-'+str(max_year)+': '+str(max_snow)+'")') else: plt.plot(x_axis, snow_accum[max_loc,:], color='#084081', linewidth=3, label='Max ('+str(max_year-1)+'-'+str(max_year)+': '+str(max_snow)+'")') # Overlay Record Min Snow Year if min_loc==current_loc: plt.plot(x_axis_end, snow_accum[min_loc,0:last_day], color='#66ff99', linewidth=3, label='Min ('+str(min_year-1)+'-'+str(min_year)+': '+str(min_snow)+'")') else: plt.plot(x_axis, snow_accum[min_loc,:], color='#66ff99', linewidth=3, label='Min ('+str(min_year-1)+'-'+str(min_year)+': '+str(min_snow)+'")') # Overlay Average SNOW plt.plot(x_axis, average_snow[:], color='#e6b800', linewidth=3, markeredgecolor='white', label='Avg ('+str(avg_snow)+'")') # Overlay Current Snow Year plt.plot(x_axis_end, current_data, color='black', linewidth=3, label='Current ('+str(current_year-1)+'-'+str(current_year)+': '+str(current_snow)+'")') plt.plot(x_axis_end[last_day-1],current_last, marker='o', color='black', markersize=10) # Plot Legend plt.legend(bbox_to_anchor=(0., -.102, 1., -1.02), loc=3, ncol=4, mode="expand", borderaxespad=0., fontsize=12) # Plot X/Y Limits ymin=0 ymax=int(5 * round(float((np.max(snow_accum) + 10))/5)) plt.ylim(ymin,ymax) plt.xlim(-5, num_days) # Plot Y-Axis Label plt.yticks(range(ymin, ymax, 10), [r'{}"'.format(x) for x in range(ymin, ymax, 10)], fontsize=10) plt.ylabel(r'Accumulated Snowfall (inches)', fontsize=12) # Plot X-Axis Label month_pos=[0,31,60,91,121,152,182,213,244,274,305,335] month_names=["Oct","Nov","Dec","Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep"] plt.xticks(month_pos, month_names, fontsize=10) # Plot 2nd Y Axis Labels ax3 = ax1.twinx() plt.yticks(range(ymin, ymax, 10), [r'{}"'.format(x) for x in range(ymin, ymax, 10)], fontsize=10) plt.ylim(ymin, ymax) # Plot Title/Subtitle plt.suptitle(station_id+': '+ghcnd_name, fontsize=20) plt.title('LAT= '+str(ghcnd_lat)+' | LON= '+str(ghcnd_lon)+' | ELEV= '+str(int(ghcnd_alt*3.2808399))+'\'', fontsize=15) # Save Figure plt.savefig(station_id+'_snowfall.png', dpi=300) plt.clf() return None
def plot_temperature(station_id,begin_date,end_date): print("\nPLOTTING TEMPERATURE DATA FOR STATION: ",station_id) # Declare Other Variables begin_year=1895 num_elements=2 # TMAX/TMIN tmax=0 tmin=1 end_year=datetime.now().year num_years=(end_year-begin_year) + 1 # Get station metadatafile ghcnd_stations=gp.get_ghcnd_stations() ghcnd_meta = ghcnd_stations[ghcnd_stations[:,0] == station_id] ghcnd_id=ghcnd_meta[0][0] ghcnd_lat=float(ghcnd_meta[0][1]) ghcnd_lon=float(ghcnd_meta[0][2]) ghcnd_alt=float(ghcnd_meta[0][3]) ghcnd_name=ghcnd_meta[0][5] ghcnd_name = ghcnd_name.strip() ghcnd_name = re.sub(' +',' ',ghcnd_name) ghcnd_name = ghcnd_name.replace(" ","_") # Grab Data gp.get_data_station(station_id) ################################################# # Read in GHCN-D Data (Original, QC'd data removed) infile = station_id+".dly" ghcnd_value = np.zeros((num_years,12,31,num_elements),dtype='f')-(9999.0) file_handle = open(infile, 'r') contents = file_handle.readlines() file_handle.close() for counter in xrange(len(contents)): element = contents[counter][17:21] if element == "TMAX" or element == "TMIN": if element == "TMAX": element_counter=tmax if element == "TMIN": element_counter=tmin year = int(contents[counter][11:15]) year_counter = year-begin_year month = int(contents[counter][15:17]) month_counter = month-1 char=21 for day_counter in xrange(0,31): if contents[counter][char:char+5] != "-9999" and contents[counter][char+6:char+7] == " ": ghcnd_value[year_counter][month_counter][day_counter][element_counter] = float(contents[counter][char:char+5]) / 10.0 char = char + 8 # Mask Missing, convert from C to F ghcnd_nonmiss = ma.masked_values(ghcnd_value, -9999.) ghcnd_nonmiss=(ghcnd_nonmiss*1.8) + 32 # Get Record / Average Values for every day in year # For averages, use 1981-2010 record_max_ghcnd = np.zeros((12,31),dtype='f')-(9999.0) record_min_ghcnd = np.zeros((12,31),dtype='f')-(9999.0) average_max_ghcnd = np.zeros((12,31),dtype='f')-(9999.0) average_min_ghcnd = np.zeros((12,31),dtype='f')-(9999.0) for month_counter in xrange(0,12): for day_counter in xrange(0,31): record_max_ghcnd[month_counter,day_counter] = ma.max(ghcnd_nonmiss[:,month_counter,day_counter,tmax]) record_min_ghcnd[month_counter,day_counter] = ma.min(ghcnd_nonmiss[:,month_counter,day_counter,tmin]) average_max_ghcnd[month_counter,day_counter] = ma.average(ghcnd_nonmiss[(1980-begin_year):(2010-begin_year),month_counter,day_counter,tmax]) average_min_ghcnd[month_counter,day_counter] = ma.average(ghcnd_nonmiss[(1980-begin_year):(2010-begin_year),month_counter,day_counter,tmin]) ################################################# # Gather Data based Upon Date Requested begin_yy = int(begin_date[0:4]) begin_mm = int(begin_date[4:6]) begin_dd = int(begin_date[6:8]) end_yy = int(end_date[0:4]) end_mm = int(end_date[4:6]) end_dd = int(end_date[6:8]) num_days = (date(end_yy, end_mm, end_dd) - date(begin_yy, begin_mm, begin_dd)).days num_days=num_days+1 num_months = ((date(end_yy, end_mm, end_dd).year - date(begin_yy, begin_mm, begin_dd).year)*12 +\ date(end_yy, end_mm, end_dd).month - date(begin_yy, begin_mm, begin_dd).month) + 1 record_max = np.zeros((num_days),dtype='f')-(9999.0) record_min = np.zeros((num_days),dtype='f')-(9999.0) average_max = np.zeros((num_days),dtype='f')-(9999.0) average_min = np.zeros((num_days),dtype='f')-(9999.0) raw_max = np.zeros((num_days),dtype='f')-(9999.0) raw_min = np.zeros((num_days),dtype='f')-(9999.0) month_pos = np.zeros((num_months),dtype='i')-(9999.0) month_names = np.empty((num_months),dtype='S7') num_days=0 num_months=0 for year_counter in xrange(begin_yy,end_yy+1): if year_counter == begin_yy: start_month=begin_mm end_month=12 elif year_counter == end_yy: start_month=1 end_month=end_mm else: start_month=1 end_month=12 for month_counter in xrange(start_month,end_month+1): month_pos[num_months] = num_days month_names[num_months] = calendar.month_name[month_counter][0:3]+" '"+str(year_counter)[2:4] for day_counter in xrange(begin_dd,end_dd+1): try: # Check if date is valid datetime(year=year_counter,month=month_counter,day=day_counter) record_max[num_days] = record_max_ghcnd[month_counter-1,day_counter-1] record_min[num_days] = record_min_ghcnd[month_counter-1,day_counter-1] average_max[num_days] = average_max_ghcnd[month_counter-1,day_counter-1] average_min[num_days] = average_min_ghcnd[month_counter-1,day_counter-1] raw_max[num_days] = ghcnd_nonmiss[year_counter-begin_year,month_counter-1,day_counter-1,tmax] raw_min[num_days] = ghcnd_nonmiss[year_counter-begin_year,month_counter-1,day_counter-1,tmin] num_days=num_days+1 except: pass num_months=num_months+1 x_axis=range(num_days) ################################################# # PLOT fig, ax1 = plt.subplots(figsize=(15, 8), edgecolor='white', facecolor='white', dpi=300) # Add grid lines plt.grid(color='black', linestyle='--', linewidth=0.5, alpha=0.3) # Plot Record TMAX/TMIN plt.bar(x_axis, record_max - record_min, bottom=record_min, edgecolor='none', color='#c3bba4', width=1, label="Record Max/Min") # Plot Average TMAX/TMIN plt.bar(x_axis, average_max - average_min, bottom=average_min, edgecolor='none', color='#9a9180', width=1, label="Average Max/Min") # Plot Raw TMAX/TMIN plt.bar(x_axis, raw_max - raw_min, bottom=raw_min, edgecolor='black', linewidth=0.5, color='#5a3b49', width=1, label="Actual Max/Min") # Find New Max/Min Records new_max_records = raw_max[raw_max >= record_max] new_min_records = raw_min[raw_min <= record_min] # Plot New Max/Min Records plt.scatter(np.where(raw_max >= record_max)[0] + 0.5, new_max_records + 1.25, s=15, zorder=10, color='#d62728', alpha=0.75, linewidth=0, label="New Max Record") plt.scatter(np.where(raw_min <= record_min)[0] + 0.5, new_min_records - 1.25, s=15, zorder=10, color='#1f77b4', alpha=0.75, linewidth=0, label="New Min Record") # Plot Legend plt.legend(bbox_to_anchor=(0., -.102, 1., -1.02), loc=3, ncol=5, mode="expand", borderaxespad=0., fontsize=12) # Plot X/Y Limits ymin=int(5 * round(float((min(record_min) - 10))/5)) ymax=int(5 * round(float((max(record_max) + 10))/5)) plt.ylim(ymin, ymax) plt.xlim(-5, (num_days)) # Plot Y-Axis Label plt.yticks(range(ymin, ymax, 10), [r'{}$^\circ$'.format(x) for x in range(ymin, ymax, 10)], fontsize=10) plt.ylabel(r'Temperature ($^\circ$F)', fontsize=12) # Plot X-Axis Label plt.xticks(month_pos, month_names, fontsize=10) # Plot 2nd Y Axis Labels ax3 = ax1.twinx() plt.yticks(range(ymin, ymax, 10), [r'{}$^\circ$'.format(x) for x in range(ymin, ymax, 10)], fontsize=10) plt.ylim(ymin, ymax) # Plot Title/Subtitle plt.suptitle(station_id+': '+ghcnd_name, fontsize=20) plt.title('LAT= '+str(ghcnd_lat)+' | LON= '+str(ghcnd_lon)+' | ELEV= '+str(int(ghcnd_alt*3.2808399))+'\'', fontsize=15) # Save Figure plt.savefig(station_id+'_temperature.png', dpi=300) plt.clf() return None