def process_chronology(self): """ sets the aggregatin depth for aggregating geospatial tiles aggregation depth varies between 3 and 20 with 20 being the most fine-grain, specific level of spatial depth """ if isinstance(self.chrono_pivot, list): for proj in self.chrono_pivot: project_key = proj['value'] if project_key not in self.projects: self.projects[project_key] = {} min_date = False max_date = False if 'pivot' in proj: for chrono_data in proj['pivot']: chrono_t = ChronoTile() dates = chrono_t.decode_path_dates( chrono_data['value']) if isinstance(dates, dict): if min_date is False: min_date = dates['earliest_bce'] max_date = dates['latest_bce'] else: if min_date > dates['earliest_bce']: min_date = dates['earliest_bce'] if max_date < dates['latest_bce']: max_date = dates['latest_bce'] self.projects[project_key]['min_date'] = min_date self.projects[project_key]['max_date'] = max_date
def decode_event_path(self, event_path): """ decodes an event path, with chrono_path tiles as the first two characters of each level, with the geo tile as the last character """ chrono_prefix = '' if self.CHRONO_PREFIX_EVENT_SEP in event_path: event_ex = event_path.split(self.CHRONO_PREFIX_EVENT_SEP) chrono_prefix = event_ex[0] event_path = event_ex[1] event_path_list = event_path.split(self.LEVEL_DELIM) chrono_path = '' geo_path = '' for event_tile in event_path_list: chrono_path = self.add_to_path(event_tile[0], chrono_path, self.CHRONO_TILE_DEPTH) chrono_path = self.add_to_path(event_tile[1], chrono_path, self.CHRONO_TILE_DEPTH) geo_path = self.add_to_path(event_tile[2], geo_path, self.GEO_TILE_DEPTH) chrono_path = chrono_prefix + chrono_path ch = ChronoTile() gm = GlobalMercator() output = { 'chrono_path': chrono_path, 'chrono': ch.decode_path_dates(chrono_path), 'geo_path': geo_path, 'geo': gm.quadtree_to_lat_lon(geo_path) } return output
def decode_event_path(self, event_path): """ decodes an event path, with chrono_path tiles as the first two characters of each level, with the geo tile as the last character """ chrono_prefix = '' if self.CHRONO_PREFIX_EVENT_SEP in event_path: event_ex = event_path.split(self.CHRONO_PREFIX_EVENT_SEP) chrono_prefix = event_ex[0] event_path = event_ex[1] event_path_list = event_path.split(self.LEVEL_DELIM) chrono_path = '' geo_path = '' for event_tile in event_path_list: chrono_path = self.add_to_path(event_tile[0], chrono_path, self.CHRONO_TILE_DEPTH) chrono_path = self.add_to_path(event_tile[1], chrono_path, self.CHRONO_TILE_DEPTH) geo_path = self.add_to_path(event_tile[2], geo_path, self.GEO_TILE_DEPTH) chrono_path = chrono_prefix + chrono_path ch = ChronoTile() gm = GlobalMercator() output = {'chrono_path': chrono_path, 'chrono': ch.decode_path_dates(chrono_path), 'geo_path': geo_path, 'geo': gm.quadtree_to_lat_lon(geo_path)} return output
def process_chronology(self): """ sets the aggregatin depth for aggregating geospatial tiles aggregation depth varies between 3 and 20 with 20 being the most fine-grain, specific level of spatial depth """ if isinstance(self.chrono_pivot, list): for proj in self.chrono_pivot: project_key = proj['value'] if project_key not in self.projects: self.projects[project_key] = {} min_date = False max_date = False if 'pivot' in proj: for chrono_data in proj['pivot']: chrono_t = ChronoTile() dates = chrono_t.decode_path_dates(chrono_data['value']) if isinstance(dates, dict): if min_date is False: min_date = dates['earliest_bce'] max_date = dates['latest_bce'] else: if min_date > dates['earliest_bce']: min_date = dates['earliest_bce'] if max_date < dates['latest_bce']: max_date = dates['latest_bce'] self.projects[project_key]['min_date'] = min_date self.projects[project_key]['max_date'] = max_date
def encode_path_from_geo_chrono(self, lat, lon, latest_bce_ce, earliest_bce_ce, chrono_prefix=''): """ encodes an event path from numeric lat, lon, and date values """ gm = GlobalMercator() geo_path = gm.lat_lon_to_quadtree(lat, lon) ch = ChronoTile() chrono_path = ch.encode_path_from_bce_ce(latest_bce_ce, earliest_bce_ce, chrono_prefix) return self.encode_path_from_geo_chrono_paths(geo_path, chrono_path)
def get_form_use_life_chronotile_query_dict(raw_chrono_tile): """Makes a filter query for formation-use-life chrono-tile string""" return make_tile_query_dict( raw_tile_path=raw_chrono_tile, solr_field='form_use_life_chrono_tile', max_path_length=ChronoTile().MAX_TILE_DEPTH, )
def _process_chrono(self): """ Finds chronological / date ranges in GeoJSON features for indexing. More than 1 date range per item is OK. """ self.chrono_specified = False if 'features' in self.oc_item.json_ld: for feature in self.oc_item.json_ld['features']: bad_time = False try: # time is in ISO 8601 time iso_start = feature['when']['start'] except KeyError: bad_time = True try: # time is in ISO 8601 time iso_stop = feature['when']['stop'] except KeyError: bad_time = True try: when_type = feature['when']['type'] except KeyError: when_type = False try: ref_type = feature['when']['reference-type'] if ref_type == 'specified': self.chrono_specified = True except KeyError: ref_type = False if when_type == 'oc-gen:formation-use-life' \ and bad_time is False: # convert GeoJSON-LD ISO 8601 to numeric start = ISOyears().make_float_from_iso(iso_start) stop = ISOyears().make_float_from_iso(iso_stop) chrono_tile = ChronoTile() if 'form_use_life_chrono_tile' not in self.fields: self.fields['form_use_life_chrono_tile'] = [] if 'form_use_life_chrono_earliest' not in self.fields: self.fields['form_use_life_chrono_earliest'] = [] if 'form_use_life_chrono_latest' not in self.fields: self.fields['form_use_life_chrono_latest'] = [] self.fields['form_use_life_chrono_tile'].append( chrono_tile.encode_path_from_bce_ce( start, stop, '10M-' ) ) self.fields['form_use_life_chrono_earliest'].append(start) self.fields['form_use_life_chrono_latest'].append(stop)
def _process_chrono(self): """ Finds chronological / date ranges in GeoJSON features for indexing. More than 1 date range per item is OK. """ self.chrono_specified = False if "features" in self.oc_item.json_ld: for feature in self.oc_item.json_ld["features"]: bad_time = False try: # time is in ISO 8601 time iso_start = feature["when"]["start"] except KeyError: bad_time = True try: # time is in ISO 8601 time iso_stop = feature["when"]["stop"] except KeyError: bad_time = True try: when_type = feature["when"]["type"] except KeyError: when_type = False try: ref_type = feature["when"]["reference-type"] if ref_type == "specified": self.chrono_specified = True except KeyError: ref_type = False if when_type == "oc-gen:formation-use-life" and bad_time is False: # convert GeoJSON-LD ISO 8601 to numeric start = ISOyears().make_float_from_iso(iso_start) stop = ISOyears().make_float_from_iso(iso_stop) chrono_tile = ChronoTile() if "form_use_life_chrono_tile" not in self.fields: self.fields["form_use_life_chrono_tile"] = [] if "form_use_life_chrono_earliest" not in self.fields: self.fields["form_use_life_chrono_earliest"] = [] if "form_use_life_chrono_latest" not in self.fields: self.fields["form_use_life_chrono_latest"] = [] self.fields["form_use_life_chrono_tile"].append( chrono_tile.encode_path_from_bce_ce(start, stop, "10M-") ) self.fields["form_use_life_chrono_earliest"].append(start) self.fields["form_use_life_chrono_latest"].append(stop)
def encode_path_from_geo_chrono_paths(self, geo_path, chrono_path): """ encodes a path bringing together a geo_path and a chrono_path """ chrono_prefix = '' if ChronoTile().PREFIX_DELIM in chrono_path: # get the range prefix for the chrono_path, # and remove it from the path cpathex = chrono_path.split(ChronoTile().PREFIX_DELIM) chrono_prefix = cpathex[0] chrono_prefix += ChronoTile().PREFIX_DELIM chrono_path = cpathex[1] c_path_len = len(chrono_path) g_path_len = len(geo_path) event_levels = c_path_len / 2 if event_levels < g_path_len: event_levels = g_path_len event_path_list = [] chrono_i = 0 geo_i = 0 while len(event_path_list) < event_levels: if chrono_i < c_path_len: ctile_a = chrono_path[chrono_i] else: ctile_a = '0' if (chrono_i + 1) < c_path_len: ctile_b = chrono_path[chrono_i + 1] else: ctile_b = '0' chrono_i += 2 if geo_i < g_path_len: geo_tile = geo_path[geo_i] else: geo_tile = '0' geo_i += 1 event_tile = ctile_a + ctile_b + geo_tile event_path_list.append(event_tile) event_path = chrono_prefix + self.CHRONO_PREFIX_EVENT_SEP + self.LEVEL_DELIM.join( event_path_list) return event_path
def _make_valid_options_tile_dicts(self, options_tuples): """Makes a list of valid tile_dicts from a list of options_tuples""" valid_tile_dicts = [] for tile, count in options_tuples: if (self.limiting_tile is not None and not tile.startswith(self.limiting_tile)): # We're looking only for tiles within a limiting # tile, and the current tile is not within that. # So skip. continue # Parse the tile to get date ranges. chrono_t = ChronoTile() tile_dict = chrono_t.decode_path_dates(tile) if not isinstance(tile_dict, dict): # Not a valid data for some awful reason. continue if (self.exclude_before is not None and tile_dict['earliest_bce'] < self.exclude_before): # The date range is too early. continue if (self.exclude_after is not None and tile_dict['latest_bce'] > self.exclude_after): # The date range is too late. continue if self.min_date is None: self.min_date = tile_dict['earliest_bce'] if self.max_date is None: self.max_date = tile_dict['latest_bce'] if self.min_date > tile_dict['earliest_bce']: self.min_date = tile_dict['earliest_bce'] if self.max_date < tile_dict['latest_bce']: self.max_date = tile_dict['latest_bce'] tile_dict['tile_key'] = tile tile_dict['count'] = count valid_tile_dicts.append(tile_dict) return valid_tile_dicts
def add_filters_json(self, request_dict): """ adds JSON describing search filters """ fl = FilterLinks() fl.base_search_link = self.base_search_link filters = [] string_fields = [] # so we have an interface for string searches i = 0 for param_key, param_vals in request_dict.items(): if param_key == 'path': if param_vals: i += 1 f_entity = self.m_cache.get_entity(param_vals) label = http.urlunquote_plus(param_vals) act_filter = LastUpdatedOrderedDict() act_filter['id'] = '#filter-' + str(i) act_filter['oc-api:filter'] = 'Context' act_filter['label'] = label.replace('||', ' OR ') if f_entity: act_filter['rdfs:isDefinedBy'] = f_entity.uri # generate a request dict without the context filter rem_request = fl.make_request_sub(request_dict, param_key, param_vals) act_filter['oc-api:remove'] = fl.make_request_url(rem_request) act_filter['oc-api:remove-json'] = fl.make_request_url(rem_request, '.json') filters.append(act_filter) else: for param_val in param_vals: i += 1 remove_geodeep = False act_filter = LastUpdatedOrderedDict() act_filter['id'] = '#filter-' + str(i) if self.hierarchy_delim in param_val: all_vals = param_val.split(self.hierarchy_delim) else: all_vals = [param_val] if param_key == 'proj': # projects, only care about the last item in the parameter value act_filter['oc-api:filter'] = 'Project' label_dict = self.make_filter_label_dict(all_vals[-1]) act_filter['label'] = label_dict['label'] if len(label_dict['entities']) == 1: act_filter['rdfs:isDefinedBy'] = label_dict['entities'][0].uri elif param_key == 'prop': # prop, the first item is the filter-label # the last is the filter act_filter['label'] = False if len(all_vals) < 2: act_filter['oc-api:filter'] = 'Description' act_filter['oc-api:filter-slug'] = all_vals[0] else: filt_dict = self.make_filter_label_dict(all_vals[0]) act_filter['oc-api:filter'] = filt_dict['label'] if 'slug' in filt_dict: act_filter['oc-api:filter-slug'] = filt_dict['slug'] if filt_dict['data-type'] == 'string': act_filter['label'] = 'Search Term: \'' + all_vals[-1] + '\'' if act_filter['label'] is False: label_dict = self.make_filter_label_dict(all_vals[-1]) act_filter['label'] = label_dict['label'] elif param_key == 'type': act_filter['oc-api:filter'] = 'Open Context Type' if all_vals[0] in QueryMaker.TYPE_MAPPINGS: type_uri = QueryMaker.TYPE_MAPPINGS[all_vals[0]] label_dict = self.make_filter_label_dict(type_uri) act_filter['label'] = label_dict['label'] else: act_filter['label'] = all_vals[0] elif param_key == 'q': act_filter['oc-api:filter'] = self.TEXT_SEARCH_TITLE act_filter['label'] = 'Search Term: \'' + all_vals[0] + '\'' elif param_key == 'id': act_filter['oc-api:filter'] = 'Identifier Lookup' act_filter['label'] = 'Identifier: \'' + all_vals[0] + '\'' elif param_key == 'form-chronotile': act_filter['oc-api:filter'] = 'Time of formation, use, or life' chrono = ChronoTile() dates = chrono.decode_path_dates(all_vals[0]) if isinstance(dates, dict): act_filter['label'] = 'Time range: ' + str(dates['earliest_bce']) act_filter['label'] += ' to ' + str(dates['latest_bce']) elif param_key == 'form-start': act_filter['oc-api:filter'] = 'Earliest formation, use, or life date' try: val_date = int(float(all_vals[0])) except: val_date = False if val_date is False: act_filter['label'] = '[Invalid year]' elif val_date < 0: act_filter['label'] = str(val_date * -1) + ' BCE' else: act_filter['label'] = str(val_date) + ' CE' elif param_key == 'form-stop': act_filter['oc-api:filter'] = 'Latest formation, use, or life date' try: val_date = int(float(all_vals[0])) except: val_date = False if val_date is False: act_filter['label'] = '[Invalid year]' elif val_date < 0: act_filter['label'] = str(val_date * -1) + ' BCE' else: act_filter['label'] = str(val_date) + ' CE' elif param_key == 'disc-geotile': act_filter['oc-api:filter'] = 'Location of discovery or observation' act_filter['label'] = self.make_geotile_filter_label(all_vals[0]) remove_geodeep = True elif param_key == 'disc-bbox': act_filter['oc-api:filter'] = 'Location of discovery or observation' act_filter['label'] = self.make_bbox_filter_label(all_vals[0]) remove_geodeep = True elif param_key == 'images': act_filter['oc-api:filter'] = 'Has related media' act_filter['label'] = 'Linked to images' elif param_key == 'other-media': act_filter['oc-api:filter'] = 'Has related media' act_filter['label'] = 'Linked to media (other than images)' elif param_key == 'documents': act_filter['oc-api:filter'] = 'Has related media' act_filter['label'] = 'Linked to documents' elif param_key == 'dc-subject': act_filter['oc-api:filter'] = 'Has subject metadata' label_dict = self.make_filter_label_dict(all_vals[-1]) if len(label_dict['label']) > 0: act_filter['label'] = label_dict['label'] if 'tdar' == all_vals[-1] or 'tdar*' == all_vals[-1]: act_filter['label'] = 'tDAR defined metadata record(s)' if len(label_dict['entities']) == 1: act_filter['rdfs:isDefinedBy'] = label_dict['entities'][0].uri if label_dict['entities'][0].vocabulary is not False: act_filter['label'] += ' in ' + label_dict['entities'][0].vocabulary elif param_key == 'dc-spatial': act_filter['oc-api:filter'] = 'Has spatial metadata' label_dict = self.make_filter_label_dict(all_vals[-1]) if len(label_dict['label']) > 0: act_filter['label'] = label_dict['label'] if len(label_dict['entities']) == 1: act_filter['rdfs:isDefinedBy'] = label_dict['entities'][0].uri if label_dict['entities'][0].vocabulary is not False: act_filter['label'] += ' in ' + label_dict['entities'][0].vocabulary elif param_key == 'dc-coverage': act_filter['oc-api:filter'] = 'Has coverage / period metadata' label_dict = self.make_filter_label_dict(all_vals[-1]) if len(label_dict['label']) > 0: act_filter['label'] = label_dict['label'] if len(label_dict['entities']) == 1: act_filter['rdfs:isDefinedBy'] = label_dict['entities'][0].uri if label_dict['entities'][0].vocabulary is not False: act_filter['label'] += ' in ' + label_dict['entities'][0].vocabulary elif param_key == 'dc-temporal': act_filter['oc-api:filter'] = 'Has temporal coverage' label_dict = self.make_filter_label_dict(all_vals[-1]) if len(label_dict['label']) > 0: act_filter['label'] = label_dict['label'] if len(label_dict['entities']) == 1: if label_dict['entities'][0].entity_type == 'vocabulary': act_filter['label'] = 'Concepts defined by: ' + label_dict['label'] elif 'periodo' in all_vals[-1]: act_filter['label'] = 'PeriodO defined concepts' if len(label_dict['entities']) == 1: act_filter['rdfs:isDefinedBy'] = label_dict['entities'][0].uri if label_dict['entities'][0].vocabulary is not False\ and label_dict['entities'][0].vocabulary != label_dict['label']: act_filter['label'] += ' in ' + label_dict['entities'][0].vocabulary elif param_key == 'obj': act_filter['oc-api:filter'] = 'Links (in some manner) to object' label_dict = self.make_filter_label_dict(all_vals[-1]) if len(label_dict['label']) > 0: act_filter['label'] = label_dict['label'] if len(label_dict['entities']) == 1: act_filter['rdfs:isDefinedBy'] = label_dict['entities'][0].uri if label_dict['entities'][0].vocabulary is not False: act_filter['label'] += ' in ' + label_dict['entities'][0].vocabulary elif param_key == 'dc-isReferencedBy': act_filter['oc-api:filter'] = 'Is referenced by' label_dict = self.make_filter_label_dict(all_vals[-1]) if len(label_dict['label']) > 0: act_filter['label'] = label_dict['label'] if len(label_dict['entities']) == 1: act_filter['rdfs:isDefinedBy'] = label_dict['entities'][0].uri if label_dict['entities'][0].vocabulary is not False\ and label_dict['entities'][0].vocab_uri != label_dict['entities'][0].uri: act_filter['label'] += ' in ' + label_dict['entities'][0].vocabulary elif param_key == 'linked' and all_vals[-1] == 'dinaa-cross-ref': act_filter['oc-api:filter'] = 'Has cross references' act_filter['label'] = 'Links to, or with, DINAA curated site files' else: act_filter = False if act_filter is not False: rem_request = fl.make_request_sub(request_dict, param_key, param_val) if 'geodeep' in rem_request and remove_geodeep: rem_request.pop('geodeep', None) act_filter['oc-api:remove'] = fl.make_request_url(rem_request) act_filter['oc-api:remove-json'] = fl.make_request_url(rem_request, '.json') filters.append(act_filter) return filters
def make_chronology_facet_options(self, solr_json): """Makes chronology facets from a solr_json response""" chrono_path_keys = ( configs.FACETS_SOLR_ROOT_PATH_KEYS + ['form_use_life_chrono_tile'] ) chrono_val_count_list = utilities.get_dict_path_value( chrono_path_keys, solr_json, default=[] ) if not len(chrono_val_count_list): return None options_tuples = utilities.get_facet_value_count_tuples( chrono_val_count_list ) if not len(options_tuples): return None # Check to see if the client included any request parameters # that limited the chronological range of the request. self._set_client_earliest_latest_limits() valid_tile_dicts = self._make_valid_options_tile_dicts( options_tuples ) if not len(valid_tile_dicts): # None of the chronological tiles are valid # given the query requirements. return None # Determine the aggregation depth needed to group chronological # tiles together into a reasonable number of options. self._get_tile_aggregation_depth(valid_tile_dicts) aggregate_tiles = {} for tile_dict in valid_tile_dicts: # Now aggregate the tiles. trim_tile_key = tile_dict['tile_key'][:self.default_aggregation_depth] if trim_tile_key not in aggregate_tiles: # Make the aggregate tile dictionary # object. chrono_t = ChronoTile() agg_dict = chrono_t.decode_path_dates(trim_tile_key) if (self.min_date is not None and agg_dict['earliest_bce'] < self.min_date): # The aggregated date range looks too early, so # set it to the earliest allowed. agg_dict['earliest_bce'] = self.min_date if (self.max_date is not None and agg_dict['latest_bce'] > self.max_date): # The aggregated date range looks too late, so # set it to the latest date range allowed. agg_dict['latest_bce'] = self.max_date agg_dict['tile_key'] = trim_tile_key agg_dict['count'] = 0 aggregate_tiles[trim_tile_key] = agg_dict aggregate_tiles[trim_tile_key]['count'] += tile_dict['count'] agg_tile_list = [tile_dict for _, tile_dict in aggregate_tiles.items()] # Now sort by earliest bce, then reversed latest bce # this makes puts early dates with longest timespans first sorted_agg_tiles = sorted( agg_tile_list, key=lambda k: (k['earliest_bce'], -k['latest_bce']) ) options = [] for tile_dict in sorted_agg_tiles: sl = SearchLinks( request_dict=copy.deepcopy(self.request_dict), base_search_url=self.base_search_url ) # Remove non search related params. sl.remove_non_query_params() # Update the request dict for this facet option. sl.replace_param_value( 'form-chronotile', match_old_value=None, new_value=tile_dict['tile_key'], ) sl.replace_param_value( 'form-start', match_old_value=None, new_value=tile_dict['earliest_bce'], ) sl.replace_param_value( 'form-stop', match_old_value=None, new_value=tile_dict['latest_bce'], ) urls = sl.make_urls_from_request_dict() if urls['html'] == self.current_filters_url: # The new URL matches our current filter # url, so don't add this facet option. continue option = LastUpdatedOrderedDict() option['id'] = urls['html'] option['json'] = urls['json'] option['count'] = tile_dict['count'] option['category'] = 'oc-api:chrono-facet' option['start'] = ISOyears().make_iso_from_float( tile_dict['earliest_bce'] ) option['stop'] = ISOyears().make_iso_from_float( tile_dict['latest_bce'] ) properties = LastUpdatedOrderedDict() properties['early bce/ce'] = tile_dict['earliest_bce'] properties['late bce/ce'] = tile_dict['latest_bce'] option['properties'] = properties options.append(option) return options
def __init__(self): self.CHRONO_TILE_DEPTH = ChronoTile().MAX_TILE_DEPTH self.GEO_TILE_DEPTH = GlobalMercator().MAX_ZOOM self.LEVEL_DELIM = '-' # so as not to get confused with the chrono-path '-' prefix self.CHRONO_PREFIX_EVENT_SEP = 'e-'
def add_non_hierarchy_filter_json( self, param_key, act_val, act_filter, param_config, request_dict, ): """Adds JSON for non-hierarchy filters. :param str param_key: Client request query parameter :param str act_val: URL unquoted client request search value :param dict act_filter: Dictionary describing the search filter associated with the param_key and act_val. :param dict param_config: Configuration dictionary for translating the param_key and act_val into an act_filter. :param dict request_dict: Dictionary object of the GET request from the client. """ if param_config.get('label'): act_filter['label'] = param_config['label'] elif param_config.get('label-template'): act_filter['label'] = param_config['label-template'].format( act_val=act_val) if param_key in ['form-start', 'form-stop']: # Case for filters on years. act_date = utilities.string_to_int(act_val) if act_date is None: act_filter['label'] = 'Invalid year. Must be integer value' elif act_date < 0: act_filter['label'] = '{} BCE'.format(act_date) else: act_filter['label'] = '{} CE'.format(act_date) elif param_key == 'form-chronotile': chrono = ChronoTile() dates = chrono.decode_path_dates(act_val) if isinstance(dates, dict): act_filter['label'] = 'Time range: {} to {}'.format( dates['earliest_bce'], dates['latest_bce'], ) else: act_filter['label'] = 'Invalid chronology encoding' elif param_key == 'disc-geotile': act_filter['label'] = make_geotile_filter_label(act_val) elif param_key == 'disc-bbox': act_filter['label'] = make_bbox_filter_label(act_val) # Add the removal links. act_filter = self.add_links_to_act_filter( param_key, match_old_value=None, new_value=None, act_filter=act_filter, request_dict=request_dict, ) return act_filter
def process_solr_tiles(self, solr_tiles): """ processes the solr_json discovery geo tiles, aggregating to a certain depth """ # first aggregate counts for tile that belong togther aggregate_tiles = LastUpdatedOrderedDict() i = -1 t = 0 if len(solr_tiles) <= 10: # don't aggregate if there's not much to aggregate self.aggregation_depth = self.max_depth for tile_key in solr_tiles[::2]: t += 1 i += 2 solr_facet_count = solr_tiles[i] if tile_key != 'false': if self.limiting_tile is False: ok_to_add = True else: # constrain to show facets ONLY within # the current queried tile if self.limiting_tile in tile_key: ok_to_add = True else: ok_to_add = False if ok_to_add: # first get full date range for # facets that are OK to add chrono_t = ChronoTile() dates = chrono_t.decode_path_dates(tile_key) if isinstance(dates, dict): if self.min_date is False: self.min_date = dates['earliest_bce'] self.max_date = dates['latest_bce'] else: if self.min_date > dates['earliest_bce']: self.min_date = dates['earliest_bce'] if self.max_date < dates['latest_bce']: self.max_date = dates['latest_bce'] # now aggregrate the OK to use facets trim_tile_key = tile_key[:self.aggregation_depth] if trim_tile_key not in aggregate_tiles: aggregate_tiles[trim_tile_key] = 0 aggregate_tiles[trim_tile_key] += solr_facet_count # now generate GeoJSON for each tile region # print('Chronology tiles: ' + str(t) + ' reduced to ' + str(len(aggregate_tiles))) # -------------------------------------------- # code to sort the list of tiles by start date and time span # -------------------------------------------- sorting_ranges = [] for tile_key, aggregate_count in aggregate_tiles.items(): chrono_t = ChronoTile() dates = chrono_t.decode_path_dates(tile_key) dates['tile_key'] = tile_key sorting_ranges.append(dates) # now sort by earliest bce, then reversed latest bce # this makes puts early dates with longest timespans first sorted_ranges = sorted(sorting_ranges, key=lambda k: (k['earliest_bce'], -k['latest_bce'])) sorted_tiles = LastUpdatedOrderedDict() for sort_range in sorted_ranges: tile_key = sort_range['tile_key'] sorted_tiles[tile_key] = aggregate_tiles[tile_key] i = 0 for tile_key, aggregate_count in sorted_tiles.items(): i += 1 fl = FilterLinks() fl.base_request_json = self.filter_request_dict_json fl.spatial_context = self.spatial_context new_rparams = fl.add_to_request('form-chronotile', tile_key) record = LastUpdatedOrderedDict() record['id'] = fl.make_request_url(new_rparams) record['json'] = fl.make_request_url(new_rparams, '.json') record['count'] = aggregate_count record['category'] = 'oc-api:chrono-facet' chrono_t = ChronoTile() dates = chrono_t.decode_path_dates(tile_key) # convert numeric to GeoJSON-LD ISO 8601 record['start'] = ISOyears().make_iso_from_float(dates['earliest_bce']) record['stop'] = ISOyears().make_iso_from_float(dates['latest_bce']) properties = LastUpdatedOrderedDict() properties['early bce/ce'] = dates['earliest_bce'] properties['late bce/ce'] = dates['latest_bce'] record['properties'] = properties self.chrono_tiles.append(record)
def process_solr_tiles(self, solr_tiles): """ processes the solr_json discovery geo tiles, aggregating to a certain depth """ # first aggregate counts for tile that belong togther aggregate_tiles = LastUpdatedOrderedDict() i = -1 t = 0 if len(solr_tiles) <= 10: # don't aggregate if there's not much to aggregate self.aggregation_depth = self.max_depth for tile_key in solr_tiles[::2]: t += 1 i += 2 solr_facet_count = solr_tiles[i] if tile_key != 'false': if self.limiting_tile is False: ok_to_add = True else: # constrain to show facets ONLY within # the current queried tile if self.limiting_tile in tile_key: ok_to_add = True else: ok_to_add = False if ok_to_add: # first get full date range for # facets that are OK to add chrono_t = ChronoTile() dates = chrono_t.decode_path_dates(tile_key) if isinstance(dates, dict): if self.min_date is False: self.min_date = dates['earliest_bce'] self.max_date = dates['latest_bce'] else: if self.min_date > dates['earliest_bce']: self.min_date = dates['earliest_bce'] if self.max_date < dates['latest_bce']: self.max_date = dates['latest_bce'] # now aggregrate the OK to use facets trim_tile_key = tile_key[:self.aggregation_depth] if trim_tile_key not in aggregate_tiles: aggregate_tiles[trim_tile_key] = 0 aggregate_tiles[trim_tile_key] += solr_facet_count # now generate GeoJSON for each tile region # print('Chronology tiles: ' + str(t) + ' reduced to ' + str(len(aggregate_tiles))) # -------------------------------------------- # code to sort the list of tiles by start date and time span # -------------------------------------------- sorting_ranges = [] for tile_key, aggregate_count in aggregate_tiles.items(): chrono_t = ChronoTile() dates = chrono_t.decode_path_dates(tile_key) dates['tile_key'] = tile_key sorting_ranges.append(dates) # now sort by earliest bce, then reversed latest bce # this makes puts early dates with longest timespans first sorted_ranges = sorted(sorting_ranges, key=lambda k: (k['earliest_bce'], -k['latest_bce'])) sorted_tiles = LastUpdatedOrderedDict() for sort_range in sorted_ranges: tile_key = sort_range['tile_key'] sorted_tiles[tile_key] = aggregate_tiles[tile_key] i = 0 for tile_key, aggregate_count in sorted_tiles.items(): i += 1 fl = FilterLinks() fl.base_request_json = self.filter_request_dict_json fl.spatial_context = self.spatial_context new_rparams = fl.add_to_request('form-chronotile', tile_key) record = LastUpdatedOrderedDict() record['id'] = fl.make_request_url(new_rparams) record['json'] = fl.make_request_url(new_rparams, '.json') record['count'] = aggregate_count record['category'] = 'oc-api:chrono-facet' chrono_t = ChronoTile() dates = chrono_t.decode_path_dates(tile_key) # convert numeric to GeoJSON-LD ISO 8601 record['start'] = ISOyears().make_iso_from_float( dates['earliest_bce']) record['stop'] = ISOyears().make_iso_from_float( dates['latest_bce']) properties = LastUpdatedOrderedDict() properties['early bce/ce'] = dates['earliest_bce'] properties['late bce/ce'] = dates['latest_bce'] record['properties'] = properties self.chrono_tiles.append(record)