def get_station_data(form_input, program): ''' Retrieves Station Data from ACIS. Keyword arguments: form_input -- parameter file for data request obtained from user of CSC pages program -- specifies program that is making the request. Returns python dictionary with keys: meta data ''' request = {'data':[]} s_date, e_date = WRCCUtils.start_end_date_to_eight(form_input) #Sanity check for valid date input: if (s_date.lower() == 'por' or e_date.lower() == 'por') and ('station_id' not in form_input.keys()): error = 'Parameter error. Start/End date ="por" not supported for multi station call.' resultsdict['error'] = error return resultsdict variables = WRCCUtils.get_variable_list(form_input, program) elems_list = [] elems_list_short = [] resultsdict = {} for el in variables: el_strip, base_temp = WRCCUtils.get_el_and_base_temp(el) elems_list_short.append(el_strip) if el_strip in ['gdd', 'hdd', 'cdd'] and base_temp is not None: d = dict(vX=WRCCData.ACIS_ELEMENTS_DICT[el_strip]['vX'], base=int(base_temp), add='f,t') elems_list.append(d) else: d = dict(vX=WRCCData.ACIS_ELEMENTS_DICT[el]['vX'],add='f,t') elems_list.append(d) params = { 'sdate':s_date, 'edate':e_date, 'meta':'name,state,sids,ll,elev,uid,valid_daterange', 'elems':elems_list } shape_type = None #Deal with POR input dates if 'station_id' in form_input.keys(): sid = form_input['station_id'] s = s_date.lower() e = e_date.lower() l = elems_list_short vd, no_vd_els = WRCCUtils.find_valid_daterange(sid, start_date=s, end_date=e, el_list=l, max_or_min='max') params['sdate'] = v[0]; params['edate'] = v[1] if params['sdate'] == '9999-99-99' or params['edate'] == '9999-99-99': error = 'No start/end date could be found for this station in the metadata database.' resultsdict['error'] = error return resultsdict #Set area parameter try: key = WRCCData.STN_AREA_FORM_TO_PARAM[form_input['select_stations_by']] val = form_input[form_input['select_stations_by']] except: key = WRCCData.STN_AREA_FORM_TO_PARAM[form_input['area_type']] val = form_input[form_input['area_type']] params[key] = val #Find bbox if custom shape and update params['bbox'] if 'shape' in form_input.keys(): shape_type,bbox = WRCCUtils.get_bbox(form_input['shape']) params['bbox'] = bbox #Data request try: req = MultiStnData(params) except Exception, e: request['error'] = 'StnData request failed. Error: %s. Pameters: %s.' %(str(e), params) return request
def get_grid_data(form_input, program): ''' Retrieves Grid Data from ACIS. Keyword arguments: form_input -- parameter file for data request obtained from user of CSC pages program -- specifies program that is making the request. Returns python dictionary with keys: meta data or smry (if data_summary) lats -- lists of latitudes for grid points lons -- lists of longitudes for grid points ''' #datalist[date_idx] = [[date1,lat1, lon1, elev1, el1_val1, el2_val1, ...], #[date2, lat2, ...], ...] s_date, e_date = WRCCUtils.start_end_date_to_eight(form_input) #grid data calls do not except list of variables, need to be string of comma separated values el_list = WRCCUtils.get_variable_list(form_input, program) if 'data_summary' in form_input.keys() and form_input['data_summary'] == 'temporal_summary': variables = [{'name':str(el),'smry':str(form_input['temporal_summary']),'smry_only':1} for el in el_list] else: variables = ','.join(el_list) params = { 'sdate': s_date, 'edate': e_date, 'grid': form_input['grid'], 'elems': variables, 'meta': 'll,elev' } #Set area parameter try: key = WRCCData.GRID_AREA_FORM_TO_PARAM[form_input['select_grid_by']] val = form_input[form_input['select_grid_by']] except: key = WRCCData.GRID_AREA_FORM_TO_PARAM[form_input['area_type']] val = form_input[form_input['area_type']] params[key] = val #Override area parameter if needed #Find bbox if custom shape if 'shape' in form_input.keys(): #Need to find enclosing bbox shape_type,bbox = WRCCUtils.get_bbox(form_input['shape']) if shape_type == 'location':params['loc'] = form_input['shape'] else:params['bbox'] = bbox #Find enclosing bbox via General ACIS call if climdiv, cwa, county, basin #Note: gridACIS currently does not support direct calls for these options #FIX me : when gridACIS supports calls for climdiv, cwa, county, basin if form_input['select_grid_by'] in ['county_warning_area', 'climate_division', 'basin', 'county']: try: a = WRCCData.STN_AREA_FORM_TO_PARAM[form_input['select_grid_by']] v = form_input[form_input['select_grid_by']] except: a = WRCCData.STN_AREA_FORM_TO_PARAM[form_input['area_type']] v = form_input[form_input['area_type']] bbox = get_acis_bbox_of_area(a,v) params['bbox'] = bbox request = {} try: request = GridData(params) except Exception, e: error = 'GridData request failed with ERROR: %s.' %(str(e)) request['error'] = error
def station_meta_to_json(by_type, val, el_list=None, time_range=None, constraints=None): ''' Requests station meta data from ACIS and writes results to a json file This json file is read by the javascript function initialize_station_map which generates the station finder map Keyword arguments: by_type -- station selection argument. station selection is one of: county, climate_division, bounding box county_warning_area, basin, state, states or custom shapes val -- Value of station selection argument, e.g, AL if by_type = state el_list -- List of var_majors of climate variables (default None --> we look for for any of the 11 common variables) time_range -- User form start and end dates [start_date, end_date] (default None --> we take valid_daterange of el_list) contraints -- specifies variable contsraints and date contsraints: any_any, all_all, any_all, all_any If el_list and time_range are given, only stations that have variables for the given time range are listed. ''' def stn_in_poly(by_type, shape_type, shape,stn_meta): #convert to floats s = [float(s) for s in shape] if shape_type == 'circle': poly = s stn_in = WRCCUtils.point_in_circle(stn_meta['ll'][0], stn_meta['ll'][1], poly) else: if shape_type in ['bbox','location']: poly = [(s[0],s[1]), (s[0],s[3]),(s[2],s[3]),(s[2],s[1])] else: poly = [(s[2*idx],s[2*idx+1]) for idx in range(len(s)/2)] stn_in = WRCCUtils.point_in_poly(stn_meta['ll'][0], stn_meta['ll'][1], poly) if not stn_in:return False else:return True def station_invalid(el_list, vX_list, time_range, stn, contraints): #Check if constraints are met for variable list and date range if constraints in ['any_any', 'any_all']: flag_invalid_station = True elif constraints in ['all_all', 'all_any']: flag_invalid_station = False for el_idx, el_vX in enumerate(el_list): #Find correct index in vX_list try: idx = vX_list.index(el_vX) except: if constraints in ['all_all', 'all_any']: flag_invalid_station = True break elif constraints in ['any_any', 'any_all']: continue #Sanity Check if not stn['valid_daterange'][idx] and (constraints == 'all_all' or constraints == 'all_any' or constraints is None): #data for this variable does not exist at station flag_invalid_station = True break elif not stn['valid_daterange'][idx] and (constraints == 'any_any' or constraints == 'any_all'): continue #Find period of record for this variable and station por_start = WRCCUtils.date_to_datetime(stn['valid_daterange'][idx][0]) por_end = WRCCUtils.date_to_datetime(stn['valid_daterange'][idx][1]) if time_range[0].lower() != 'por': user_start = WRCCUtils.date_to_datetime(time_range[0]) else: user_start = por_start if time_range[1].lower() != 'por': user_end = WRCCUtils.date_to_datetime(time_range[1]) else: user_end = por_end #Check constraints logic for this variable and station if constraints == 'all_all' or constraints is None: #all variables have data records for all dates within start and end date given by user if user_start < por_start or user_end > por_end: flag_invalid_station = True break elif constraints == 'any_any': #At least one variable has one data record within user given time_range if (user_end >= por_start and user_start <= por_end) or (user_start <= por_end and user_end >=por_start): flag_invalid_station = False break elif constraints == 'all_any': #All variables have at least one data record within user given time_range if (user_end >= por_start and user_start <= por_end) or (user_start <= por_end and user_end >=por_start): continue else: flag_invalid_station = True break elif constraints == 'any_all': #At least one variables has data records for all dates within given date_range if user_start >= por_start and user_end <= por_end: flag_invalid_station = False break return flag_invalid_station #Settings stn_list = [] stn_json={ 'network_codes': WRCCData.KELLY_NETWORK_CODES, 'network_icons': WRCCData.KELLY_NETWORK_ICONS, 'overlay_type':by_type, 'overlay_val':val } if el_list: vX_list = [str(el) for el in el_list] vX_tuple = ','.join(vX_list) else: vX_list= ['1','2','43','3','4','10','11','7','45','44','12'] vX_tuple = '1,2,43,3,4,10,11,7,45,44,12' shape_type = None time_stamp = datetime.datetime.now().strftime('%Y_%m_%d_%H_%M_%S_') f_name = time_stamp + 'stn.json' f_dir = settings.TEMP_DIR #Set up metedata request params = {'meta':'name,state,sids,ll,elev,uid,valid_daterange','elems':vX_tuple} params[WRCCData.STN_AREA_FORM_TO_PARAM[by_type]] = val if by_type == 'sw_states':params['state'] = 'az,ca,co,nm,nv,ut' #Find bbox for custom shapes if by_type == 'shape': shape_type,bbox = WRCCUtils.get_bbox(val) params['bbox'] = bbox #Acis Metadata call and sanity checks on results try: request = StnMeta(params) except: stn_json['error'] = 'Metadata request failed. Please check your parameters!' WRCCUtils.load_data_to_json_file(f_dir + f_name, stn_json) return stn_json, f_name if request is None: stn_json['error'] = 'No metadata found.' WRCCUtils.load_data_to_json_file(f_dir + f_name, stn_json) return stn_json, f_name if not 'meta' in request.keys() or not request['meta'] or 'error' in request.keys(): stn_json['error'] = 'No metadata found.' WRCCUtils.load_data_to_json_file(f_dir + f_name, stn_json) return stn_json, f_name stn_meta_list = [] #For alphabetic ordering of station names sorted_list =[] #Keep track of duplicates unique_stations = [] for i, stn in enumerate(request['meta']): #if custom shape, check if stn lies within shape if by_type == 'shape': if shape_type in ['bbox','location']:shape = bbox.split(',') elif shape_type == 'polygon':shape = WRCCUtils.orient_shape_ccw(val).split(',') else:shape = val.split(',') if not stn_in_poly(by_type, shape_type, shape, stn): continue #sanity check if not stn['valid_daterange']: continue #check if we are looking for stations with particular variables if el_list is not None and time_range is not None: #Check if ACIS produced correct output, i.e. one valid_daterange per variable if len(stn['valid_daterange']) < len(el_list): continue #Check if station is valid, if not, proceed to next station flag_invalid_station = station_invalid(el_list, vX_list, time_range, stn, constraints) if flag_invalid_station: continue stn_sids = [] stn_networks = [] stn_network_codes = [] sids = stn['sids'] if 'sids' in stn.keys() else [] marker_icons = [] for sid in sids: sid_split = sid.split(' ') ''' #put coop id up front (for csc application metagraph and possibly others) if str(sid_split[1]) == '2': #stn_sids.append(re.sub('[^a-zA-Z0-9\n\.]', ' ', str(sid_split[1]))) stn_sids.insert(0,str(sid_split[0]).replace("\'"," ")) stn_network_codes.insert(0, str(sid_split[1])) marker_icons.insert(0, WRCCData.NETWORK_ICONS[str(sid_split[1])]) stn_networks.insert(0,WRCCData.NETWORK_CODES[str(sid_split[1])]) else: ''' #stn_sids.append(re.sub('[^a-zA-Z0-9\n\.]', ' ', str(sid_split[1]))) stn_sids.append(str(sid_split[0]).replace("\'"," ")) stn_network_codes.append(str(sid_split[1])) if int(sid_split[1]) <= 10: stn_networks.append(WRCCData.NETWORK_CODES[str(sid_split[1])]) marker_icons.append(WRCCData.NETWORK_ICONS[str(sid_split[1])]) else: stn_networks.append('Misc') marker_icons.append('red') #Sanity check : Some Acis records are incomplete, leading to key error if 'll' in stn.keys(): lat = str(stn['ll'][1]) lon = str(stn['ll'][0]) else: continue try: #name = re.sub('[^a-zA-Z0-9\n\.]', ' ', str(stn['name'])) if 'name' in stn.keys() else 'Name not listed' name = str(stn['name']).replace("\'"," ").replace('#','') if 'name' in stn.keys() else 'Name not listed' except: name = 'Name not listed' uid = str(stn['uid']) if 'uid' in stn.keys() else 'Uid not listed' elev = str(stn['elev']) if 'elev' in stn.keys() else 'Elevation not listed' state_key = str(stn['state']).lower() if 'state' in stn.keys() else 'state not listed' #sort station networks so that coop is last #so that coop markers show on map stn_networks_sorted = [] for n in stn_networks: if n !='COOP': stn_networks_sorted.append(n) if 'COOP' in stn_networks: stn_networks_sorted.append('COOP') #Generate one entry per network that the station belongs to for j, sid in enumerate(stn_networks_sorted): stn_dict = { 'name':name, 'uid':uid, 'sid':stn_sids[j], 'sids':stn_sids, 'sids_str':','.join(stn_sids), 'elevation':elev, 'lat':lat, 'lon':lon, 'll':str(lon) + ', ' + str(lat), 'state':state_key, 'marker_icon':marker_icons[j], 'marker_category':stn_networks[j], 'stn_networks':stn_networks, 'stn_network':','.join(stn_networks), 'stn_network_codes': stn_network_codes } #check which variables are available at the stations[valid_daterange is not empty] valid_date_range_list = stn['valid_daterange'] available_variables = [] available_variables_str = '' for j,rnge in enumerate(valid_date_range_list): if rnge and len(rnge) >=2: vd = [str(rnge[0]), str(rnge[1])] vd_str = ' - '.join(vd) if WRCCData.ACIS_ELEMENTS[vX_list[j]]['name'] == 'cdd': el_name = WRCCData.ACIS_ELEMENTS['-44']['name_long'] else: el_name = WRCCData.ACIS_ELEMENTS[vX_list[j]]['name_long'] available_variables.append([el_name,vd]) available_variables_str+=el_name + ': ' + vd_str + ', ' if available_variables: stn_dict['available_variables'] = available_variables stn_dict['available_variables_str'] = available_variables_str[0:-2] #find index in alphabetically ordered list of station names sorted_list.append(name.split(' ')[0]) try: sorted_list.sort() stn_idx = sorted_list.index(name.split(' ')[0]) except ValueError: stn_idx = -1 #Insert stn into alphabeticlly ordered list if stn_idx == -1: stn_meta_list.append(stn_dict) else: stn_meta_list.insert(stn_idx, stn_dict) stn_json['stations'] = stn_meta_list WRCCUtils.load_data_to_json_file(f_dir + f_name, stn_json) return stn_json, f_name