From 8e050e555f91a5bce875281d83c2381503195b8f Mon Sep 17 00:00:00 2001 From: Joshua Miller Date: Mon, 17 Oct 2016 17:51:15 -0500 Subject: [PATCH 01/37] wip --- esbuild/graph/common/builder.py | 640 ++--------------------------- tests/test_graph_active_builder.py | 1 + tests/test_suite_data.gv.pdf | Bin 46207 -> 46203 bytes 3 files changed, 30 insertions(+), 611 deletions(-) diff --git a/esbuild/graph/common/builder.py b/esbuild/graph/common/builder.py index c32fe105..f6f4fd45 100644 --- a/esbuild/graph/common/builder.py +++ b/esbuild/graph/common/builder.py @@ -11,7 +11,6 @@ from cdisutils.log import get_logger from collections import defaultdict from copy import copy, deepcopy -from datadog import statsd from gdcdatamodel import models as md from psqlgraph import Node, Edge from sqlalchemy.orm import joinedload @@ -22,18 +21,19 @@ import random import re +from esbuild.graph.common import ( + util, +) + +from esbuild.shared_graph import ( + CachingOptions +) + from .mappings import ( ONE_TO_MANY, ONE_TO_ONE, ) -from progressbar import ( - ProgressBar, - Percentage, - Bar, - ETA, -) - log = get_logger("graph_index") log.setLevel(level=logging.INFO) @@ -78,18 +78,8 @@ class GraphIndexBuilder(object): remembering which nodes are walked through a lot and remembering which neighbors they have with a given label. - NOTE: An attempt was made to do this whole thing in parallel, - however the memory footprint grew to large. The best method for - doing this is to use the main process as a workload distributer, - and have child processes denormalizing cases. This way, - the main thread can upsert files on an outbound queue from child - processes. - - Josh (jsmiller@uchicago.edu) - TODOS: - - figure out a way to parallelize without excess copies - =============== Transformations =============== @@ -161,11 +151,20 @@ class GraphIndexBuilder(object): ] ] - def __init__(self, psqlgraph_driver): + + def get_caching_options(self): + return CachingOptions( + case_to_file_paths=self.case_to_file_paths, + redacted_but_not_suppressed=self.redacted_but_not_suppressed, + ) + + def __init__(self, shared_graph): """Walks the graph to produce elasticsearch json documents. """ + self.shared_graph = shared_graph + # Verify required attributes are set for required_attr in self.required_attrs: if getattr(self, required_attr) is None: @@ -188,25 +187,7 @@ def __init__(self, psqlgraph_driver): # Get the actual case mapping to validate against self.case_es_mapping = self.mapper.get_case_es_mapping() - self.g = psqlgraph_driver - self.G = nx.Graph() - self.leaf_nodes = ['center', 'tissue_source_site'] - self.experimental_strategies = {} - self.data_categories = {} - self.popular_nodes = {} - self.cases = None - self.projects = None - self.relevant_nodes = None - self.annotations = None - self.annotation_entities = None - self.entity_cases = None - - # Different from ``self.data_categories`` in that it's a - # replacement for a hardcoded dict of data_type, data_subtype - # relationships. This is populated by - # ``self._cache_existing_data_types()`` - self.existing_data_types = {} # Suppress entities with redaction annotation if # entity.annotation.category not in this list @@ -264,40 +245,17 @@ def __init__(self, psqlgraph_driver): '.tbi', } - def warning(self, title, text, tags=[], *args, **kwargs): - log.warning("{}: {}".format(title, text)) - statsd.event( - title, - text, - source_type_name="esbuild", - alert_type="warning", - tags=tags, - ) + @staticmethod + def warning(*args, **kwargs): + """Log a warning to logger and statsd""" - def error(self, title, text, tags=[], *args, **kwargs): - log.error("{}: {}".format(title, text)) - statsd.event( - title, - text, - source_type_name="esbuild", - alert_type="error", - tags=tags, - ) + util.log_warning(log, *args, **kwargs) - def pbar(self, title, maxval): - """Create and initialize a custom progressbar + @staticmethod + def error(*args, **kwargs): + """Log a error to logger and statsd""" - :param str title: The text of the progress bar - :param int maxval: The maximumum value of the progress bar - - """ - maxval = maxval or 1 # prevent maxal of 0 - pbar = ProgressBar(widgets=[ - title, Percentage(), ' ', - Bar(marker='#', left='[', right=']'), ' ', - ETA(), ' '], maxval=maxval) - pbar.update(0) - return pbar + util.log_error(log, *args, **kwargs) ################################################################### # Tree functions @@ -436,14 +394,8 @@ def walk_paths(self, node, paths, whole=False): ]) } - def remove_bam_index_files(self, files): - return { - f for f in files - if not self.is_index_file(f) - } - ################################################################### - # Cases + # cases ################################################################## def remove_hidden_nodes(self, nodes): @@ -1227,7 +1179,7 @@ def denormalize_cases(self, cases=None): case_docs, ann_docs, file_docs = [], {}, {} if not cases: cases = self.cases - pbar = self.pbar('Denormalizing cases ', len(cases)) + pbar = util.get_pbar('Denormalizing cases ', len(cases)) for n in cases: pa, fi, an = self.denormalize_case(n) case_docs.append(pa) @@ -1251,7 +1203,7 @@ def denormalize_projects(self, projects=None): if not projects: projects = self.projects project_docs = [] - pbar = self.pbar('Denormalizing projects ', len(projects)) + pbar = util.get_pbar('Denormalizing projects ', len(projects)) for project in projects: project_docs.append(self.denormalize_project(project)) pbar.update(pbar.currval+1) @@ -1327,70 +1279,6 @@ def denormalize_sample(self, k=10): projects = self.denormalize_projects(projs) return cases, files, annotations, projects - ################################################################### - # Graph functions - ################################################################### - - def nodes_labeled(self, labels): - """Returns an iterator over the edges in the graph with label `label` - - """ - - labels = tuple(labels) if hasattr(labels, '__iter__') else (labels,) - for n, p in self.G.nodes_iter(data=True): - if n.label in labels: - yield n - - @staticmethod - def node_labels_by_category(categories): - """Returns an iterator of node labels that are files - - """ - - categories = ( - tuple(categories) if hasattr(categories, '__iter__') - else (categories,) - ) - - return [ - n.label for n in Node.get_subclasses() - if n._dictionary['category'] in categories - ] - - def neighbors_labeled(self, node, labels, expected=None): - """For a given node, return an iterator with generates neighbors to - that node that are in a list of labels. `label` can be either a - string or list of strings. - - :param is_expected: Int count of expected elements - - """ - labels = tuple(labels) if hasattr(labels, '__iter__') else (labels,) - - if node in self.popular_nodes: - if labels not in self.popular_nodes[node]: - neighbors = self._cache_popular_neighbor( - node, self.G.neighbors(node), labels) - else: - neighbors = self.popular_nodes[node][labels] - else: - temp = self.G.neighbors(node) - if len(temp) > 200: - neighbors = self._cache_popular_neighbor(node, temp, labels) - else: - neighbors = {n for n in temp if n.label in labels} - - count = 0 - for n in neighbors: - count += 1 - yield n - - if expected is not None and count != expected: - self.warning( - "{}: unexpected no. of '{}' neighbors".format(node, labels), - '{}: {} != {} (expected)'.format(node, count, expected), - tags=["{}:{}".format(node.label, node.node_id)]) - ################################################################### # Validation functions ################################################################### @@ -1491,144 +1379,6 @@ def validate_case(self, node, case): # Check for keys that are in the doc but not in the mapping self.validate_against_mapping(case, self.case_es_mapping) - ################################################################### - # Caching functions - ################################################################### - - @staticmethod - def is_harmonized_file(node): - return ( - node.label == 'file' and - node._sysan.get('source', '').endswith('_alignment') - ) - - def is_old_supplement_file(self, node): - return ( - node.label == 'file' and - any( - p.match(node._props.get('file_name', '')) - for p in self.supplement_regexes - ) - ) - - def is_file_indexed(self, node): - """Returns false if node is a file that is not supposed to be indexed. - - """ - - # This function should only be for files - if node.label not in self.file_labels: - return True - - # Remove files with no acl entries - if len(node.acl) == 0: - log.info('File not indexed (empty acl): %s', node) - return False - - # Skip old versions of supplement xmls - if self.is_old_supplement_file(node): - log.info('File not indexed (deprecated supplement): %s', node) - return False - - # Skip old representation of harmonized files - if self.is_harmonized_file(node): - log.info('File not indexed (deprecated harmonized file): %s', node) - return False - - # Is file to_delete - if node.system_annotations.get("to_delete"): - return False - - # Is file not live - if node.state not in ['live', 'submitted']: - log.info('File not indexed (bad state: %s): %s', node, node.state) - return False - - return True - - def is_omitted_project_or_neighbor_case(self, node): - """Returns false if the node is a project that is not supposed to be - indexed. - - """ - - if node.label == 'project': - projects = [node] - elif node.label == 'case': - projects = list(self.neighbors_labeled(node, 'project', 1)) - else: - return False - - project_codes = [project.code for project in projects] - program_names = [ - program.name - for project in projects - for program in self.neighbors_labeled(project, 'program', 1) - ] - - # Check if project is not released - for project in projects: - if project.released is not True: - log.info('Omitting %s, project %s not released', node, project) - return True - - # Check project and program against omitted_projects - for program_name in program_names: - for project_code in project_codes: - if (program_name, project_code) in self.omitted_projects: - return True - - return False - - def is_unindexed_case(self, node): - return ( - node.label == 'case' - and not list(self.neighbors_labeled(node, 'project', 1)) - ) - - def is_node_unindexed_by_property(self, node): - """Returns True if node should be removed because its properties are - specified in self.unindexed_by_property as an indication to - remove it from the index. - - """ - - filters = self.unindexed_by_property.get(node.label, []) - - for filter_ in filters: - is_subset = not set(filter_.items()) - set(node._props.items()) - - if is_subset: - return True - - return False - - def is_node_indexed(self, node): - """Returns false if the node is not supposed to be indexed. - - """ - - if self.is_unindexed_case(node): - log.info('Node not indexed (case not indexed): {}'.format(node)) - return False - - # Check for non-indexed files - if not self.is_file_indexed(node): - log.info('Node not indexed (file not indexed): {}'.format(node)) - return False - - # Check for non-indexed files - if self.is_node_unindexed_by_property(node): - log.info('Node not indexed (not by property): {}'.format(node)) - return False - - # Check for omitted_projects - if self.is_omitted_project_or_neighbor_case(node): - log.info('Node not indexed (omitted project ): {}'.format(node)) - return False - - return True - def is_node_hidden(self, node): """Return True if the node should be traversed (and therefore must remain in the cache) but should not appear in any documents @@ -1644,218 +1394,6 @@ def is_node_hidden(self, node): return False - @staticmethod - def truncate_path(path, label): - """ - Given a path (a list of node labels), "truncate" it from the left - such that it starts with the given label, or return [], e.g.: - - truncate_path(["a", "b", "c"], "a") -> ["b", "c"] - truncate_path(["c", "d"], "b") -> [] - - """ - for i, currlabel in enumerate(path): - if currlabel == label: - return path[i+1:] - return [] - - def get_suppressed_children(self, redacted): - """Get the children of a redacted node. - - """ - to_suppress = [] - if redacted.label == "case": - paths = self.case_to_file_paths - else: - paths = [self.truncate_path(p, redacted.label) - for p in self.case_to_file_paths] - # filter empty paths - paths = [p for p in paths if p] - log.info("suppressing %s, which is redacted directly.", redacted) - to_suppress.append(redacted) - log.info("Walking down towards file with paths %s", paths) - extra = self.walk_paths(redacted, paths, whole=True) - log.info("Found %s other things to suppress by walking from %s", - extra, redacted) - to_suppress.extend(extra) - return to_suppress - - def suppressed_nodes(self): - """ - Find all nodes that need to be suppressed due to redactions. - """ - redactions = [a for a in self.nodes_labeled('annotation') - if a.classification == "Redaction" and - a.category not in self.redacted_but_not_suppressed] - to_suppress = [] - for redaction in redactions: - redacted_list = self.G.neighbors(redaction) - - if len(redacted_list) == 0: - # If there is no entity, then we have to move on to - # the next annotation - self.error( - 'Redaction annotation no entities', - "Redaction {} has zero entities associated.".format( - redaction), - tags=["annotation:{}".format(redaction)], - ) - continue - - if len(redacted_list) > 1: - # an annotation should only ever annotate one thing, - # however, proceed to redact them all - self.warning( - 'Redaction annotation has multiple entities', - ("{} has more than one entity associated. " - "For security reasons, removing all from index!") - .format(redaction), - tags=["annotation:{}".format(redaction)], - ) - - for redacted in redacted_list: - to_suppress += self.get_suppressed_children(redacted) - - # returning the redaction annotations themselves here might - # seem weird, but including the redaction annotations - # themselves without the things they point to won't work, so - # we have to remove them. - log.info("suppressing %s, the redaction annotation.", redaction) - to_suppress.append(redaction) - - return to_suppress - - def remove_unindexed_nodes_from_graph(self): - log.info('Selecting entities to be removed from cache...') - removed_nodes = [node for node in self.G.nodes() - if not self.is_node_indexed(node)] - log.info("Removing {} nodes from cache".format(len(removed_nodes))) - self.G.remove_nodes_from(removed_nodes) - log.info("Finding and removing suppressed nodes") - suppressed = self.suppressed_nodes() - log.info("Removing %s suppressed nodes", len(suppressed)) - self.G.remove_nodes_from(suppressed) - - def iter_database_edges(self): - """Returns an iterable of edges to load from the database. - - Eagerly (with join) loads the source and destination of the edge. - - """ - - return itertools.chain(*[ - self.g.edges(subclass) - .options(joinedload(subclass.src)) - .options(joinedload(subclass.dst)) - .yield_per(int(1e5)) - for subclass in Edge.__subclasses__() - ]) - - def cache_database(self): - """Load the database into memory and remember only edge labels that we - will need to distinguish later. - - """ - - with self.g.session_scope(): - pbar = self.pbar('Caching Database: ', self.g.edges().count()) - for e in self.iter_database_edges(): - pbar.update(pbar.currval+1) - triple = (e.src.label, e.label, e.dst.label) - needs_differentiation = (triple in self.differentiated_edges) - if triple == ("file", "data_from", "file"): - # for files that are "data_from" other files, the - # centers and aliquots of the source files count - # as neighbors of the dst files - for center in e.src.centers: - self.G.add_edge(e.dst, center) - for aliquot in e.src.aliquots: - self.G.add_edge(e.dst, aliquot) - if e.label == 'relates_to' and e.__dst_class__ == 'Case': - pass - elif needs_differentiation and e._props: - self.G.add_edge( - e.src, e.dst, label=e.label, props=e._props) - elif needs_differentiation and not e._props: - self.G.add_edge(e.src, e.dst, label=e.label) - elif e._props: - self.G.add_edge(e.src, e.dst, props=e._props) - else: - self.G.add_edge(e.src, e.dst) - pbar.finish() - - # Prune graph - log.info('Cached {} nodes'.format(self.G.number_of_nodes())) - self.remove_unindexed_nodes_from_graph() - - # Aggressively cache relationships, nodes by type, traversals, etc. - self._cache_all() - - def _cache_all(self): - """Create key value maps to cache nodes by label, by path, etc. - - """ - - self._cache_existing_data_types() - self._cache_experimental_strategies() - self._cache_data_categories() - self._cache_annotations() - self._cache_relevant_nodes() - self._cache_entity_cases() - self._cache_cases() - self._cache_projects() - - def _cache_projects(self): - """Save a list of all Project nodes""" - - if not self.projects: - log.info('Caching projects...') - self.projects = list(self.nodes_labeled('project')) - - def _cache_cases(self): - """Save a list of all Case nodes""" - - if not self.cases: - log.info('Caching cases...') - self.cases = list(self.nodes_labeled('case')) - - def _cache_entity_cases(self): - """Cache the related Case nodes for each file""" - - if self.entity_cases: - return - - entities = list(self.nodes_labeled(self.possible_associated_entites)) - pbar = self.pbar('Caching entity cases: ', len(entities)) - self.entity_cases = {} - - for e in entities: - if e.label == "case": - # if the associated entity is a case, it's case is - # just itself. this is kindy of sketchy but w/e - self.entity_cases[e] = e - continue - - paths = ( - self.truncate_path(path, e.label) - for path in self.file_to_case_paths - ) - cases = self.walk_paths(e, paths) - - if len(cases) > 1: - self.warning( - 'Entity associated with > 1 case', - '{}: Found {} cases'.format(e, len(cases)), - tags=["entity:{}".format(e)], - ) - return - - if len(cases) != 0: - self.entity_cases[e] = cases.pop() - - pbar.update(pbar.currval+1) - pbar.finish() - def get_cls_file_to_case_paths(self, cls): """Given a node, return the paths the lead monotonically up to case""" @@ -1868,123 +1406,3 @@ def get_cls_file_to_case_paths(self, cls): for path in self.file_to_case_paths if path and path[0] in parent_labels ) - - def _cache_relevant_nodes(self): - """The file documents will need to be pruned to only the nodes that - are relevant to the file. Here we cache all of the nodes - encountered when traversing to all related cases. - - """ - - if self.relevant_nodes: - return - - self.relevant_nodes = {} - - files = list(self.nodes_labeled(self.file_labels)) - pbar = self.pbar('Caching file paths: ', len(files)) - - for f in files: - paths = self.get_cls_file_to_case_paths(f) - self.relevant_nodes[f] = self.walk_paths(f, paths, whole=True) - pbar.update(pbar.currval+1) - - pbar.finish() - - def _cache_annotations(self): - if not self.annotations: - # cache what nodes are annotations - self.annotations = list(self.nodes_labeled('annotation')) - if self.annotation_entities: - # we've already cached the related entities - return - if not self.annotations: - # there aren't any entities to relate - self.annotation_entities = {} - log.warn('No annotations found in the cached database!') - return - pbar = self.pbar('Caching annotations: ', len(self.annotations)) - self.annotation_entities = {} - for a in self.annotations: - for n in self.G.neighbors(a): - if n not in self.annotation_entities: - self.annotation_entities[n] = {} - a_doc = self.denormalize_annotation(a) - self.annotation_entities[n][a.node_id] = a_doc - pbar.update(pbar.currval+1) - pbar.finish() - - def _cache_popular_neighbor(self, node, neighbors, labels): - if node not in self.popular_nodes: - self.popular_nodes[node] = {} - self.popular_nodes[node][labels] = { - n for n in neighbors if n.label in labels} - return self.popular_nodes[node][labels] - - def _cache_data_categories(self): - """Looking up the files that are classified in each data_type is a - common computation. Here we cache this information for easy retrieval. - - ..note:: - data_type is renamed data_category, viz. - https://jira.opensciencedatacloud.org/browse/PGDC-1472 - - """ - - if len(self.data_categories): - return - - log.info('Caching data categories') - for data_category in self.nodes_labeled('data_type'): - category = data_category._props['name'] - self.data_categories[category] = self.remove_bam_index_files( - set(self.walk_path(data_category, ['data_subtype', 'file']))) - - # New files have 'data_category' as a property - for file_ in self.nodes_labeled(self.file_labels): - category = file_._props.get('data_category') - if not category: - continue - self.data_categories.setdefault(category, set()).add(file_) - - def _cache_experimental_strategies(self): - """Looking up the files that are classified in each - experimental_strategy is a common computation. Here we cache - this information for easy retrieval. - - """ - - if len(self.experimental_strategies): - return - - log.info('Caching experitmental strategies') - for exp_strat in self.nodes_labeled('experimental_strategy'): - strategy = exp_strat._props['name'] - self.experimental_strategies[strategy] = set(self.walk_path( - exp_strat, ['file'])) - - # New files have 'experimental_strategy' as a property - for file_ in self.nodes_labeled(self.file_labels): - strategy = file_._props.get('experimental_strategy') - if not strategy: - continue - self.experimental_strategies.setdefault(strategy, set()).add(file_) - - def _cache_existing_data_types(self): - """The last version of this code imported a hard coded list and called - it DATA_TYPES. This function replaces this hardcoded nested - dict by pulling it from the graph at runtime. - - :returns: - The data types in the graph in the format - ``{'data_type.name': ['data_subtype.name']}`` - - """ - - with self.g.session_scope(): - return { - data_type.name: [ - subtype.name - for subtype in data_type.data_subtypes - ] for data_type in self.g.nodes(md.DataType).all() - } diff --git a/tests/test_graph_active_builder.py b/tests/test_graph_active_builder.py index c44afd7a..cf829e89 100644 --- a/tests/test_graph_active_builder.py +++ b/tests/test_graph_active_builder.py @@ -36,6 +36,7 @@ def index(): builder = ActiveGraphIndexBuilder(_graph) builder.cache_database() + import ipdb; ipdb.set_trace(); index = builder.denormalize_all() return Index._make(index) diff --git a/tests/test_suite_data.gv.pdf b/tests/test_suite_data.gv.pdf index c467b6871dbb106b0dd3a92426f7fd44d57ed390..22b9a27de44cb21c120cc169ac7926f71b811198 100644 GIT binary patch delta 16801 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 PshOE6m#V6(zZ(|-uO^D1 delta 16800 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 From 4257f245a407dbcf3f4331cce000a020a34d8d1c Mon Sep 17 00:00:00 2001 From: Joshua Miller Date: Mon, 17 Oct 2016 21:19:08 -0500 Subject: [PATCH 02/37] wip --- esbuild/graph/active/builder.py | 16 +- esbuild/graph/common/builder.py | 326 +++++++------- esbuild/graph/common/cache.py | 684 +++++++++++++++++++++++++++++ esbuild/graph/common/util.py | 126 ++++++ tests/test_graph_active_builder.py | 21 +- tests/test_suite_data.gv.pdf | Bin 46203 -> 46195 bytes 6 files changed, 983 insertions(+), 190 deletions(-) create mode 100644 esbuild/graph/common/cache.py create mode 100644 esbuild/graph/common/util.py diff --git a/esbuild/graph/active/builder.py b/esbuild/graph/active/builder.py index e75ae3db..7874e239 100644 --- a/esbuild/graph/active/builder.py +++ b/esbuild/graph/active/builder.py @@ -214,7 +214,7 @@ def get_parent_with_category(self, node, category): if l['dst_type']._dictionary['category'] == category ] - return self.neighbors_labeled(node, labels) + return self.cache.neighbors_labeled(node, labels) def get_child_with_category(self, node, category): """returns iterable of neighors from inbound edges with category""" @@ -224,7 +224,7 @@ def get_child_with_category(self, node, category): if l['src_type']._dictionary['category'] == category ] - return self.neighbors_labeled(node, labels) + return self.cache.neighbors_labeled(node, labels) def add_file_analysis(self, node, doc): """Add the 'analysis' that produced the current file""" @@ -315,7 +315,7 @@ def get_read_group_qc_docs(self, read_group): """Returns a list of documents for Read Group QCs""" read_group_qc_docs = [] - rg_qcs = self.neighbors_labeled(read_group, 'read_group_qc') + rg_qcs = self.cache.neighbors_labeled(read_group, 'read_group_qc') for read_group_qc in rg_qcs: read_group_qc_docs.append(self._get_base_doc(read_group_qc)) @@ -329,7 +329,7 @@ def get_file_read_groups(self, node): """ paths = self.file_to_read_group_paths.get(node.label, []) - return set(self.walk_paths(node, paths)) + return set(self.cache.walk_paths(node, paths)) def get_analysis_read_groups(self, node): """Given a analysis node, traverse up the tree to read_groups: @@ -356,7 +356,7 @@ def get_simple_file_doc(self, node): doc['data_format'] = self.get_data_format(node) - for dst in self.neighbors_labeled(node, 'data_subtype'): + for dst in self.cache.neighbors_labeled(node, 'data_subtype'): doc['data_type'] = dst['name'] return doc @@ -372,7 +372,7 @@ def get_file_associated_entities(self, node): entity for rg in self.get_file_read_groups(node) for entity in - self.neighbors_labeled(rg, self.possible_associated_entites) + self.cache.neighbors_labeled(rg, self.possible_associated_entites) ] # Add entities with one step through a data_file @@ -380,7 +380,7 @@ def get_file_associated_entities(self, node): entity for parent in self.get_parent_with_category(node, 'data_file') for entity in - self.neighbors_labeled(parent, self.possible_associated_entites) + self.cache.neighbors_labeled(parent, self.possible_associated_entites) ] # Copy number paths @@ -389,7 +389,7 @@ def get_file_associated_entities(self, node): list_product([['aliquot']], self.aliquot_to_copy_number_paths) ] entities += [ - entity for entity in self.walk_paths(node, cnv_paths) + entity for entity in self.cache.walk_paths(node, cnv_paths) ] return list(set(entities)) diff --git a/esbuild/graph/common/builder.py b/esbuild/graph/common/builder.py index f6f4fd45..9a95d5ed 100644 --- a/esbuild/graph/common/builder.py +++ b/esbuild/graph/common/builder.py @@ -25,8 +25,8 @@ util, ) -from esbuild.shared_graph import ( - CachingOptions +from esbuild.graph.common.cache import ( + CachingOptions, ) from .mappings import ( @@ -134,11 +134,9 @@ class GraphIndexBuilder(object): # "label": [{"key1": "value1", "key2": "value2"}] } - required_attrs = [ - 'mapper', - 'case_to_file_paths', - 'file_labels', - ] + # Suppress entities with redaction annotation if + # entity.annotation.category not in this list + redacted_but_not_suppressed = ['Subject withdrew consent'] supplement_regexes = [ re.compile(regex) for regex in [ @@ -151,21 +149,74 @@ class GraphIndexBuilder(object): ] ] + leaf_nodes = ['center', 'tissue_source_site'] + + # Omit entities from these projects + omitted_projects = { + ('TCGA', 'CNTL'), + ('TCGA', 'MISC'), + ('TCGA', 'TEST'), + ('TCGA', 'DEV1'), + ('TCGA', 'DEV2'), + ('TCGA', 'DEV3'), + ('TCGA', 'FPPP'), + ('GDC', 'INTERNAL'), + ('UAT08', 'BROAD-BCR'), + ('TARGET', 'AML-IF'), + } - def get_caching_options(self): - return CachingOptions( - case_to_file_paths=self.case_to_file_paths, - redacted_but_not_suppressed=self.redacted_but_not_suppressed, - ) + # The body of these nested documents will be flattened into + # the parent document using the given key's value + flatten = { + 'tag': 'name', + 'platform': 'name', + 'data_format': 'name', + 'data_subtype': 'name', + 'experimental_strategy': 'name', + 'data_level': 'name', + } + + # The edges below will maintain labels in the in memory graph, + # all others will be discarded + differentiated_edges = [ + ('file', 'member_of', 'archive'), + ('archive', 'member_of', 'file'), + ('file', 'describes', 'case'), + ('case', 'describes', 'file'), + ('file', 'related_to', 'file'), + ] + + possible_associated_entites = [ + 'portion', + 'aliquot', + 'case', + 'slide', + ] + + index_file_extensions = { + '.bai', + '.tbi', + } + + # The following attributes must be overridden + case_to_file_paths = None + mapper = None + file_labels = None - def __init__(self, shared_graph): + required_attrs = [ + 'mapper', + 'case_to_file_paths', + 'file_labels', + ] + + def __init__(self, cached_graph): """Walks the graph to produce elasticsearch json documents. """ - self.shared_graph = shared_graph + self.cache = cached_graph - # Verify required attributes are set + # verify required attributes are set for required_attr in self.required_attrs: if getattr(self, required_attr) is None: raise NotImplementedError( @@ -187,63 +238,23 @@ def __init__(self, shared_graph): # Get the actual case mapping to validate against self.case_es_mapping = self.mapper.get_case_es_mapping() - self.leaf_nodes = ['center', 'tissue_source_site'] - - # Suppress entities with redaction annotation if - # entity.annotation.category not in this list - self.redacted_but_not_suppressed = ['Subject withdrew consent'] - - # Omit entities from these projects - self.omitted_projects = { - ('TCGA', 'CNTL'), - ('TCGA', 'MISC'), - ('TCGA', 'TEST'), - ('TCGA', 'DEV1'), - ('TCGA', 'DEV2'), - ('TCGA', 'DEV3'), - ('TCGA', 'FPPP'), - ('GDC', 'INTERNAL'), - ('UAT08', 'BROAD-BCR'), - ('TARGET', 'AML-IF'), - } + self.file_to_case_paths = util.reverse_paths( + self.case_to_file_paths, 'case') - # The body of these nested documents will be flattened into - # the parent document using the given key's value - self.flatten = { - 'tag': 'name', - 'platform': 'name', - 'data_format': 'name', - 'data_subtype': 'name', - 'experimental_strategy': 'name', - 'data_level': 'name', - } + @classmethod + def get_caching_options(cls): + """Returns caching options for this builder""" - # The edges below will maintain labels in the in memory graph, - # all others will be discarded - self.differentiated_edges = [ - ('file', 'member_of', 'archive'), - ('archive', 'member_of', 'file'), - ('file', 'describes', 'case'), - ('case', 'describes', 'file'), - ('file', 'related_to', 'file'), - ] - - self.file_to_case_paths = [ - list(reversed(l))[1:]+['case'] - for l in self.case_to_file_paths - ] - - self.possible_associated_entites = [ - 'portion', - 'aliquot', - 'case', - 'slide', - ] - - self.index_file_extensions = { - '.bai', - '.tbi', - } + return CachingOptions( + case_to_file_paths=cls.case_to_file_paths, + redacted_but_not_suppressed=cls.redacted_but_not_suppressed, + differentiated_edges=cls.differentiated_edges, + file_labels=cls.file_labels, + unindexed_by_property=cls.unindexed_by_property, + omitted_projects=cls.omitted_projects, + index_file_extensions=cls.index_file_extensions, + possible_associated_entites=cls.possible_associated_entites, + ) @staticmethod def warning(*args, **kwargs): @@ -281,8 +292,8 @@ def create_tree(self, node, mapping, tree): if node.label in self.leaf_nodes: return {} submap = mapping[node.label] - corr, plural = submap['corr'] - for child in self.G.neighbors(node): + + for child in self.cache.neighbors(node): if child.label not in submap: continue tree[child] = {} @@ -296,7 +307,7 @@ def walk_tree(self, node, tree, mapping, doc, level=0, """ - corr, plural = mapping[node.label]['corr'] + corr, _ = mapping[node.label]['corr'] subdoc = self._get_base_doc(node) for child in tree[node]: child_corr, child_plural = mapping[node.label][child.label]['corr'] @@ -362,38 +373,6 @@ def _get_base_doc(self, node, include_id=True): return base - ################################################################### - # Path functions - ################################################################### - - def walk_path(self, node, path, whole=False): - """Given a list of strings, treat it as a path, and yield the end of - possible traversals. If `whole` is true, return every node - along the traversal. - - """ - - if path: - for neighbor in self.neighbors_labeled(node, path[0]): - if whole or (len(path) == 1 and path[0] == neighbor.label): - yield neighbor - - for n in self.walk_path(neighbor, path[1:], whole): - yield n - - def walk_paths(self, node, paths, whole=False): - """Given a list of paths, yield the result of walking each path. If - `whole` is true, return every node along each traversal. - - """ - - return { - n for n in itertools.chain(*[ - self.walk_path(node, path, whole=whole) - for path in paths - ]) - } - ################################################################### # cases ################################################################## @@ -415,12 +394,17 @@ def remove_hidden_nodes(self, nodes): def get_case_files(self, node): """Return a list of file nodes by walking out from case""" - files = self.walk_paths(node, self.case_to_file_paths) - files = self.remove_bam_index_files(files) + files = self.cache.walk_paths(node, self.case_to_file_paths) + files = self.remove_index_files(files) files = self.remove_hidden_nodes(files) return files + def remove_index_files(self, files): + """Partial function for util.remove_index_files""" + + return util.remove_index_files(files, self.index_file_extensions) + def get_case_tree(self, node): """Use tree to create nested json @@ -563,8 +547,8 @@ def get_exp_strats(self, files): experimental_strategy is non-null """ - self._cache_experimental_strategies() - for exp_strat, file_list in self.experimental_strategies.iteritems(): + self.cache._cache_experimental_strategies() + for exp_strat, file_list in self.cache.experimental_strategies.iteritems(): intersection = (file_list & files) if intersection: yield { @@ -578,8 +562,8 @@ def get_data_categories(self, files): data_category is non-null """ - self._cache_data_categories() - for data_category, file_list in self.data_categories.iteritems(): + self.cache._cache_data_categories() + for data_category, file_list in self.cache.data_categories.iteritems(): intersection = (file_list & files) if intersection: yield { @@ -699,7 +683,7 @@ def get_data_format(self, node): else: # get data_format from edge to DataFormat - formats = list(self.neighbors_labeled(node, 'data_format')) + formats = list(self.cache.neighbors_labeled(node, 'data_format')) # Get the first format if formats: @@ -753,9 +737,11 @@ def add_file_neighbors(self, node, doc): """ - auto_neighbors = [n for n in dict(self.ftree_mapping['file']).keys() - if n not in ['archive', 'portion', 'file']] - for neighbor in set(self.neighbors_labeled(node, auto_neighbors)): + auto_neighbors = [ + n for n in dict(self.ftree_mapping['file']).keys() + if n not in ['archive', 'portion', 'file'] + ] + for neighbor in set(self.cache.neighbors_labeled(node, auto_neighbors)): corr, label = self.ftree_mapping['file'][neighbor.label]['corr'] if neighbor.label in self.flatten: base = neighbor[self.flatten[neighbor.label]] @@ -783,24 +769,13 @@ def is_index_file(self, node): """ - # Active index files - if node._dictionary['category'] == 'index_file': - return True - - # Legacy index files - elif node.label == 'file': - for extension in self.index_file_extensions: - if node._props.get('file_name', '').endswith(extension): - return True - - else: - return False + return util.is_index_file(node, self.index_file_extensions) def get_file_index_files(self, node): """Given a file, return any neighboring index files""" return [ - n for n in list(self.neighbors_labeled(node, 'file')) - if self.G[node][n].get("label") == "related_to" + n for n in list(self.cache.neighbors_labeled(node, 'file')) + if self.cache[node][n].get("label") == "related_to" and self.is_index_file(n) ] @@ -842,19 +817,19 @@ def add_related_files(self, node, doc): # Get related_files related_files = [ - n for n in list(self.neighbors_labeled(node, 'file')) - if self.G[node][n].get("label") == "related_to" + n for n in list(self.cache.neighbors_labeled(node, 'file')) + if self.cache[node][n].get("label") == "related_to" and not self.is_index_file(n) ] - related_files += list(self.neighbors_labeled(node, metadata_labels)) + related_files += list(self.cache.neighbors_labeled(node, metadata_labels)) for related_file in related_files: rf_doc = self._get_base_doc(related_file, include_id=False) rf_doc['file_id'] = related_file.node_id # Data types - data_subtypes = self.neighbors_labeled( + data_subtypes = self.cache.neighbors_labeled( related_file, 'data_subtype', ) @@ -883,8 +858,8 @@ def add_related_files(self, node, doc): # file.archives) and one that is `related_to` (which goes # here). For now, we don't do this for non-legacy files. if node.label == 'file': - for archive in set(self.neighbors_labeled(node, 'archive')): - if self.G[node][archive].get('label') != 'member_of': + for archive in set(self.cache.neighbors_labeled(node, 'archive')): + if self.cache[node][archive].get('label') != 'member_of': name = '{}.{}.0.tar.gz'.format( archive['submitter_id'], archive['revision']) rf_docs.append({ @@ -906,7 +881,7 @@ def add_archives(self, node, doc): """ - for archive in set(self.neighbors_labeled(node, 'archive')): + for archive in set(self.cache.neighbors_labeled(node, 'archive')): if 'archive' in doc: return self.warning( "Duplicate archives for {}".format(node), @@ -916,7 +891,7 @@ def add_archives(self, node, doc): is_skipped_legacy_edge = ( node.label == 'file' and - self.G[node][archive].get('label') != 'member_of' + self.cache[node][archive].get('label') != 'member_of' ) if not is_skipped_legacy_edge: @@ -935,10 +910,9 @@ def add_data_category(self, node, doc): """ - self._cache_data_categories() data_categories = [ data_category - for data_category, files in self.data_categories.items() + for data_category, files in self.cache.data_categories.items() if node in files ] if data_categories: @@ -957,11 +931,11 @@ def add_cases(self, node, ptree, doc): log.warn('No ptree (case tree) for %s', node) return [] - if node not in self.relevant_nodes: + if node not in self.cache.relevant_nodes: log.warn('No relevant cases for %s', node) return [] - relevant = self.relevant_nodes[node] + relevant = self.cache.relevant_nodes[node] prune_keys = ['sample', 'portion', 'analyte', 'aliquot', 'file'] self.prune_case(relevant, ptree, prune_keys) @@ -987,7 +961,7 @@ def add_annotations(self, node, relevant, doc): annotations = doc.pop('annotations', []) for relevant_node in relevant: - ann_docs = self.annotation_entities.get(relevant_node, {}) + ann_docs = self.cache.annotation_entities.get(relevant_node, {}) annotations.extend(ann_docs.values()) if annotations: @@ -1015,22 +989,20 @@ def add_file_access(self, node, doc): def get_file_associated_entities(self, node): """Returns a list of entities that are 'associated' with a file""" - return list(self.neighbors_labeled( + return list(self.cache.neighbors_labeled( node, self.possible_associated_entites)) def add_file_associated_entities(self, node, doc, case_id): - self._cache_entity_cases() - docs = [] entities = self.get_file_associated_entities(node) for e in entities: - if e not in self.entity_cases: + if e not in self.cache.entity_cases: # Skip, the cases is likely missing because it is omitted continue - case = self.entity_cases[e] + case = self.cache.entity_cases[e] subdoc = { 'entity_type': e.label, 'entity_id': e.node_id, @@ -1066,11 +1038,11 @@ def denormalize_project(self, p): """Summarize a project. """ - self._cache_all() + doc = self._get_base_doc(p) # Get programs - program = self.neighbors_labeled(p, 'program').next() + program = self.cache.neighbors_labeled(p, 'program').next() log.info('Program: {}'.format(program)) doc['program'] = self._get_base_doc(program) @@ -1078,7 +1050,7 @@ def denormalize_project(self, p): self.patch_project(doc) log.info('Finding cases') - cases = list(self.neighbors_labeled(p, 'case')) + cases = list(self.cache.neighbors_labeled(p, 'case')) log.info('Got {} cases'.format(len(cases))) # Get files @@ -1086,8 +1058,8 @@ def denormalize_project(self, p): files = set() case_files = {} for case in cases: - case_files[case] = self.remove_bam_index_files( - self.walk_paths(case, self.case_to_file_paths)) + case_files[case] = self.remove_index_files( + self.cache.walk_paths(case, self.case_to_file_paths)) files = files.union(case_files[case]) # filter files @@ -1101,10 +1073,10 @@ def denormalize_project(self, p): # Get experimental strategies exp_strat_summaries = [] - self._cache_experimental_strategies() - for exp_strat in self.experimental_strategies.keys(): + self.cache._cache_experimental_strategies() + for exp_strat in self.cache.experimental_strategies.keys(): log.info('exp_strat: {}'.format(exp_strat)) - exp_files = (self.experimental_strategies[exp_strat] & files) + exp_files = (self.cache.experimental_strategies[exp_strat] & files) if not len(exp_files): continue @@ -1122,11 +1094,10 @@ def denormalize_project(self, p): # Get data types data_category_summaries = [] - self._cache_data_categories() - for data_category in self.data_categories.keys(): + for data_category in self.cache.data_categories.keys(): log.info('data_category: {}'.format(data_category)) - dt_files = (self.data_categories[data_category] & files) + dt_files = (self.cache.data_categories[data_category] & files) if not len(dt_files): continue @@ -1175,10 +1146,9 @@ def denormalize_cases(self, cases=None): """ - self._cache_all() case_docs, ann_docs, file_docs = [], {}, {} if not cases: - cases = self.cases + cases = self.cache.cases pbar = util.get_pbar('Denormalizing cases ', len(cases)) for n in cases: pa, fi, an = self.denormalize_case(n) @@ -1199,7 +1169,6 @@ def denormalize_projects(self, projects=None): """ - self._cache_all() if not projects: projects = self.projects project_docs = [] @@ -1217,8 +1186,10 @@ def denormalize_annotation(self, node): case denormalization. """ + ann_doc = self._get_base_doc(node) - entities = self.G.neighbors(node) + entities = self.cache.neighbors(node) + if len(entities) == 0: self.error( 'Annotation has no entities', @@ -1264,8 +1235,7 @@ def denormalize_cases_sample(self, k=10): documents """ - self._cache_all() - cases = random.sample(self.cases, k) + cases = random.sample(self.cache.cases, k) cases, files, annotations = self.denormalize_cases(cases) return cases, files, annotations @@ -1371,8 +1341,9 @@ def validate_case(self, node, case): if len(case['files']) != case['summary']['file_count']: self.error( 'Inconsistent case file count', - '{}: {} != {}'.format(node.node_id, len(case['files']), - case['summary']['file_count']), + '{}: {} != {}'.format( + node.node_id, len(case['files']), + case['summary']['file_count']), tags=["case_id:{}".format(node.node_id)], ) @@ -1394,15 +1365,18 @@ def is_node_hidden(self, node): return False - def get_cls_file_to_case_paths(self, cls): - """Given a node, return the paths the lead monotonically up to case""" + @staticmethod + def node_labels_by_category(categories): + """Returns an iterator of node labels that are files - parent_labels = { - link['dst_type'].label - for link in cls._pg_links.values() - } - return ( - path - for path in self.file_to_case_paths - if path and path[0] in parent_labels + """ + + categories = ( + tuple(categories) if hasattr(categories, '__iter__') + else (categories,) ) + + return [ + n.label for n in Node.get_subclasses() + if n._dictionary['category'] in categories + ] diff --git a/esbuild/graph/common/cache.py b/esbuild/graph/common/cache.py new file mode 100644 index 00000000..336f09e8 --- /dev/null +++ b/esbuild/graph/common/cache.py @@ -0,0 +1,684 @@ +# -*- coding: utf-8 -*- +""" +esbuild.graph.common.cache +---------------------------------- + +Functionality to create a multiprocessing manager to share cached +graph information between processes + +""" + +import logging +import itertools +import networkx as nx + +from gdcdatamodel import models as md +from psqlgraph import Edge, Node +from sqlalchemy.orm import joinedload + +from esbuild.graph.common import ( + util, +) + +logger = logging.getLogger(__name__) +logger.setLevel(logging.INFO) + + +class CachingOptions(object): + """An object to hold the options required to hold the required options + to cache information to a SharedGraph object + + """ + + def __init__( + self, + case_to_file_paths, + redacted_but_not_suppressed, + differentiated_edges, + file_labels, + unindexed_by_property, + omitted_projects, + index_file_extensions, + possible_associated_entites, + ): + """Options required to cache information to SharedGraph object + + :param list case_to_file_paths: + specifies all possible paths from case entities to file + entities. is a list of lists of string labels + + :param list redacted_but_not_suppressed: + Suppress entities with redaction annotation if + entity.annotation.category not in this list + + :param file_labels: + Node labels that should be treated as properties + + :param unindezed_by_property: + Filter nodes out if their properties are a superset of any of + the dictionaries listed here by label + + """ + + self.case_to_file_paths = case_to_file_paths + self.redacted_but_not_suppressed = redacted_but_not_suppressed + self.differentiated_edges = differentiated_edges + self.file_labels = file_labels + self.unindexed_by_property = unindexed_by_property + self.omitted_projects = omitted_projects + self.index_file_extensions = index_file_extensions + self.possible_associated_entites = possible_associated_entites + + self.file_to_case_paths = util.reverse_paths( + self.case_to_file_paths, 'case') + + +class CachedGraph(object): + """Represents the shared information for esbuild workers. This data + includes a cached version of the psqlgraph graph in NetworkX as + well as more aggresively cached things, e.g. relationships. + + """ + + def __init__(self, psqlgraph_driver, caching_options): + + # Injected Dependencies + self.psqlgraph_driver = psqlgraph_driver + self.graph = nx.Graph() + self.caching_options = caching_options + + # Cached information + self.experimental_strategies = {} + self.data_categories = {} + self.popular_nodes = {} + self.cases = None + self.projects = None + self.relevant_nodes = None + self.annotations = None + # FIXME + self.annotation_entities = {} + self.entity_cases = None + # Different from ``self.data_categories`` in that it's a + # replacement for a hardcoded dict of data_type, data_subtype + # relationships. This is populated by + # ``self._cache_existing_data_types()`` + self.existing_data_types = {} + + def iter_database_edges(self): + """Returns an iterable of edges to load from the database. + + Eagerly (with join) loads the source and destination of the edge. + + """ + + return itertools.chain(*[ + self.psqlgraph_driver.edges(subclass) + .options(joinedload(subclass.src)) + .options(joinedload(subclass.dst)) + .yield_per(int(1e5)) + for subclass in Edge.__subclasses__() + ]) + + @staticmethod + def warning(*args, **kwargs): + """Log a warning to logger and statsd""" + + util.log_warning(logger, *args, **kwargs) + + @staticmethod + def error(*args, **kwargs): + """Log a error to logger and statsd""" + + util.log_error(logger, *args, **kwargs) + + def get_suppressed_children(self, redacted): + """Get the children of a redacted node""" + + to_suppress = [] + if redacted.label == "case": + paths = self.caching_options.case_to_file_paths + else: + paths = [ + util.truncate_path(p, redacted.label) + for p in self.caching_options.case_to_file_paths if p + ] + + logger.info("suppressing %s, which is redacted directly.", redacted) + to_suppress.append(redacted) + + logger.info("Walking down towards file with paths %s", paths) + extra = self.walk_paths(redacted, paths, whole=True) + + logger.info("Found %s other things to suppress by walking from %s", + extra, redacted) + to_suppress.extend(extra) + + return to_suppress + + def suppressed_nodes(self): + """ + Find all nodes that need to be suppressed due to redactions. + """ + + redactions = [ + a for a in self.nodes_labeled('annotation') + if a.classification == "Redaction" and + a.category not in self.caching_options.redacted_but_not_suppressed + ] + + to_suppress = [] + for redaction in redactions: + redacted_list = self.graph.neighbors(redaction) + + if len(redacted_list) == 0: + # If there is no entity, then we have to move on to + # the next annotation + self.error( + 'Redaction annotation no entities', + "Redaction {} has zero entities associated.".format( + redaction), + tags=["annotation:{}".format(redaction)], + ) + continue + + if len(redacted_list) > 1: + # an annotation should only ever annotate one thing, + # however, proceed to redact them all + self.warning( + 'Redaction annotation has multiple entities', + ("{} has more than one entity associated. " + "For security reasons, removing all from index!") + .format(redaction), + tags=["annotation:{}".format(redaction)], + ) + + for redacted in redacted_list: + to_suppress += self.get_suppressed_children(redacted) + + # returning the redaction annotations themselves here might + # seem weird, but including the redaction annotations + # themselves without the things they point to won't work, so + # we have to remove them. + logger.info("suppressing %s, the redaction annotation.", redaction) + to_suppress.append(redaction) + + return to_suppress + + def is_unindexed_case(self, node): + return ( + node.label == 'case' + and not list(self.neighbors_labeled(node, 'project', 1)) + ) + + def is_node_indexed(self, node): + """Returns false if the node is not supposed to be indexed. + + """ + + if self.is_unindexed_case(node): + logger.info('Node not indexed (case not indexed): %s', node) + return False + + # Check for non-indexed files + if not self.is_file_indexed(node): + logger.info('Node not indexed (file not indexed): %s', node) + return False + + # Check for non-indexed files + if self.is_node_unindexed_by_property(node): + logger.info('Node not indexed (not by property): %s', node) + return False + + # Check for omitted_projects + if self.is_omitted_project_or_neighbor_case(node): + logger.info('Node not indexed (omitted project ): %s', node) + return False + + return True + + def remove_unindexed_nodes_from_graph(self): + logger.info('Selecting entities to be removed from cache...') + + removed_nodes = [ + node for node in self.graph.nodes() + if not self.is_node_indexed(node) + ] + + logger.info("Removing %s nodes from cache", len(removed_nodes)) + self.graph.remove_nodes_from(removed_nodes) + + logger.info("Finding and removing suppressed nodes") + suppressed = self.suppressed_nodes() + + logger.info("Removing %s suppressed nodes", len(suppressed)) + self.graph.remove_nodes_from(suppressed) + + def cache_database(self): + """Load the database into memory and remember only edge labels that we + will need to distinguish later. + + """ + + with self.psqlgraph_driver.session_scope(): + + pbar = util.get_pbar( + 'Caching Database: ', + self.psqlgraph_driver.edges().count()) + + for e in self.iter_database_edges(): + pbar.update(pbar.currval+1) + triple = (e.src.label, e.label, e.dst.label) + needs_differentiation = ( + triple in self.caching_options.differentiated_edges + ) + if triple == ("file", "data_from", "file"): + # for files that are "data_from" other files, the + # centers and aliquots of the source files count + # as neighbors of the dst files + for center in e.src.centers: + self.graph.add_edge(e.dst, center) + for aliquot in e.src.aliquots: + self.graph.add_edge(e.dst, aliquot) + if e.label == 'relates_to' and e.__dst_class__ == 'Case': + pass + elif needs_differentiation and e._props: + self.graph.add_edge( + e.src, e.dst, label=e.label, props=e._props) + elif needs_differentiation and not e._props: + self.graph.add_edge(e.src, e.dst, label=e.label) + elif e._props: + self.graph.add_edge(e.src, e.dst, props=e._props) + else: + self.graph.add_edge(e.src, e.dst) + pbar.finish() + + # Prune graph + logger.info('Cached {} nodes'.format(self.graph.number_of_nodes())) + self.remove_unindexed_nodes_from_graph() + + # Aggressively cache relationships, nodes by type, traversals, etc. + self._cache_all() + + def _cache_all(self): + """Create key value maps to cache nodes by label, by path, etc. + + """ + + self._cache_existing_data_types() + self._cache_experimental_strategies() + self._cache_data_categories() + self._cache_relevant_nodes() + self._cache_entity_cases() + self._cache_cases() + self._cache_projects() + # FIXME + # self._cache_annotations() + + def _cache_projects(self): + """Save a list of all Project nodes""" + + if not self.projects: + logger.info('Caching projects...') + self.projects = list(self.nodes_labeled('project')) + + def _cache_cases(self): + """Save a list of all Case nodes""" + + if not self.cases: + logger.info('Caching cases...') + self.cases = list(self.nodes_labeled('case')) + + def _cache_entity_cases(self): + """Cache the related Case nodes for each file""" + + if self.entity_cases: + return + + entities = list(self.nodes_labeled( + self.caching_options.possible_associated_entites)) + pbar = util.get_pbar('Caching entity cases: ', len(entities)) + self.entity_cases = {} + + for entity in entities: + if entity.label == "case": + # if the associated entity is a case, it's case is + # just itself. this is kindy of sketchy but w/e + self.entity_cases[entity] = entity + continue + + paths = ( + util.truncate_path(path, entity.label) + for path in self.caching_options.file_to_case_paths + ) + cases = self.walk_paths(entity, paths) + + if len(cases) > 1: + self.warning( + 'Entity associated with > 1 case', + '{}: Found {} cases'.format(entity, len(cases)), + tags=["entity:{}".format(entity)], + ) + return + + if len(cases) != 0: + self.entity_cases[entity] = cases.pop() + + pbar.update(pbar.currval+1) + pbar.finish() + + def _cache_relevant_nodes(self): + """The file documents will need to be pruned to only the nodes that + are relevant to the file. Here we cache all of the nodes + encountered when traversing to all related cases. + + """ + + if self.relevant_nodes: + return + + self.relevant_nodes = {} + + files = list(self.nodes_labeled(self.caching_options.file_labels)) + pbar = util.get_pbar('Caching file paths: ', len(files)) + + for file_ in files: + paths = util.get_file_to_case_paths( + file_, self.caching_options.file_to_case_paths) + self.relevant_nodes[file_] = self.walk_paths( + file_, paths, whole=True) + pbar.update(pbar.currval+1) + + pbar.finish() + + # def _cache_annotations(self): + # if not self.annotations: + # # cache what nodes are annotations + # self.annotations = list(self.nodes_labeled('annotation')) + # if self.annotation_entities: + # # we've already cached the related entities + # return + # if not self.annotations: + # # there aren't any entities to relate + # self.annotation_entities = {} + # logger.warn('No annotations found in the cached database!') + # return + # pbar = util.get_pbar('Caching annotations: ', len(self.annotations)) + # self.annotation_entities = {} + # for a in self.annotations: + # for n in self.graph.neighbors(a): + # if n not in self.annotation_entities: + # self.annotation_entities[n] = {} + # a_doc = self.denormalize_annotation(a) + # self.annotation_entities[n][a.node_id] = a_doc + # pbar.update(pbar.currval+1) + # pbar.finish() + + def _cache_popular_neighbor(self, node, neighbors, labels): + if node not in self.popular_nodes: + self.popular_nodes[node] = {} + self.popular_nodes[node][labels] = { + n for n in neighbors if n.label in labels} + return self.popular_nodes[node][labels] + + def _cache_data_categories(self): + """Looking up the files that are classified in each data_type is a + common computation. Here we cache this information for easy retrieval. + + ..note:: + data_type is renamed data_category, viz. + https://jira.opensciencedatacloud.org/browse/PGDC-1472 + + """ + + if len(self.data_categories): + return + + logger.info('Caching data categories') + for data_category in self.nodes_labeled('data_type'): + category = data_category._props['name'] + + self.data_categories[category] = util.remove_index_files( + set(self.walk_path(data_category, ['data_subtype', 'file'])), + self.caching_options.index_file_extensions, + ) + + # New files have 'data_category' as a property + for file_ in self.nodes_labeled(self.caching_options.file_labels): + category = file_._props.get('data_category') + if not category: + continue + self.data_categories.setdefault(category, set()).add(file_) + + def _cache_experimental_strategies(self): + """Looking up the files that are classified in each + experimental_strategy is a common computation. Here we cache + this information for easy retrieval. + + """ + + if len(self.experimental_strategies): + return + + logger.info('Caching experitmental strategies') + for exp_strat in self.nodes_labeled('experimental_strategy'): + strategy = exp_strat._props['name'] + self.experimental_strategies[strategy] = set(self.walk_path( + exp_strat, ['file'])) + + # New files have 'experimental_strategy' as a property + for file_ in self.nodes_labeled(self.caching_options.file_labels): + strategy = file_._props.get('experimental_strategy') + if not strategy: + continue + self.experimental_strategies.setdefault(strategy, set()).add(file_) + + def _cache_existing_data_types(self): + """The last version of this code imported a hard coded list and called + it DATA_TYPES. This function replaces this hardcoded nested + dict by pulling it from the graph at runtime. + + :returns: + The data types in the graph in the format + ``{'data_type.name': ['data_subtype.name']}`` + + """ + + with self.psqlgraph_driver.session_scope(): + return { + data_type.name: [ + subtype.name + for subtype in data_type.data_subtypes + ] for data_type in self.psqlgraph_driver.nodes(md.DataType) + } + + ################################################################### + # Graph functions + ################################################################### + + def nodes_labeled(self, labels): + """Returns an iterator over the edges in the graph with label `label` + + """ + + labels = tuple(labels) if hasattr(labels, '__iter__') else (labels,) + for node, _ in self.graph.nodes_iter(data=True): + if node.label in labels: + yield node + + def neighbors_labeled(self, node, labels, expected=None): + """For a given node, return an iterator with generates neighbors to + that node that are in a list of labels. `label` can be either a + string or list of strings. + + :param is_expected: Int count of expected elements + + """ + labels = tuple(labels) if hasattr(labels, '__iter__') else (labels,) + + if node in self.popular_nodes: + if labels not in self.popular_nodes[node]: + neighbors = self._cache_popular_neighbor( + node, self.graph.neighbors(node), labels) + else: + neighbors = self.popular_nodes[node][labels] + else: + temp = self.graph.neighbors(node) + if len(temp) > 200: + neighbors = self._cache_popular_neighbor(node, temp, labels) + else: + neighbors = {n for n in temp if n.label in labels} + + count = 0 + for neighbor in neighbors: + count += 1 + yield neighbor + + if expected is not None and count != expected: + self.warning( + "{}: unexpected no. of '{}' neighbors".format(node, labels), + '{}: {} != {} (expected)'.format(node, count, expected), + tags=["{}:{}".format(node.label, node.node_id)]) + + @staticmethod + def is_harmonized_file(node): + return ( + node.label == 'file' and + node._sysan.get('source', '').endswith('_alignment') + ) + + def is_old_supplement_file(self, node): + return ( + node.label == 'file' and + any( + p.match(node._props.get('file_name', '')) + for p in self.supplement_regexes + ) + ) + + def is_file_indexed(self, node): + """Returns false if node is a file that is not supposed to be indexed. + + """ + + # This function should only be for files + if node.label not in self.caching_options.file_labels: + return True + + # Remove files with no acl entries + if len(node.acl) == 0: + logger.info('File not indexed (empty acl): %s', node) + return False + + # Skip old versions of supplement xmls + if self.is_old_supplement_file(node): + logger.info('File not indexed (deprecated supplement): %s', node) + return False + + # Skip old representation of harmonized files + if self.is_harmonized_file(node): + logger.info('File not indexed (deprecated harmonized file): %s', node) + return False + + # Is file to_delete + if node.system_annotations.get("to_delete"): + return False + + # Is file not live + if node.state not in ['live', 'submitted']: + logger.info('File not indexed (bad state: %s): %s', node, node.state) + return False + + return True + + def is_omitted_project_or_neighbor_case(self, node): + """Returns false if the node is a project that is not supposed to be + indexed. + + """ + + if node.label == 'project': + projects = [node] + elif node.label == 'case': + projects = list(self.neighbors_labeled(node, 'project', 1)) + else: + return False + + project_codes = [project.code for project in projects] + program_names = [ + program.name + for project in projects + for program in self.neighbors_labeled(project, 'program', 1) + ] + + # Check if project is not released + for project in projects: + if project.released is not True: + logger.info('Omitting %s, project %s not released', + node, project) + return True + + # Check project and program against omitted_projects + for program_name in program_names: + for project_code in project_codes: + is_omitted = ( + (program_name, project_code) in + self.caching_options.omitted_projects + ) + if is_omitted: + return True + + return False + + def is_node_unindexed_by_property(self, node): + """Returns True if node should be removed because its properties are + specified in self.unindexed_by_property as an indication to + remove it from the index. + + """ + + filters = self.caching_options.unindexed_by_property.get(node.label, []) + + for filter_ in filters: + is_subset = not set(filter_.items()) - set(node._props.items()) + + if is_subset: + return True + + return False + + ################################################################### + # Path functions + ################################################################### + + def neighbors(self, node): + """Return the neighbors of given node""" + + return self.graph.neighbors(node) + + def walk_path(self, node, path, whole=False): + """Given a list of strings, treat it as a path, and yield the end of + possible traversals. If `whole` is true, return every node + along the traversal. + + """ + + if path: + for neighbor in self.neighbors_labeled(node, path[0]): + if whole or (len(path) == 1 and path[0] == neighbor.label): + yield neighbor + + for node in self.walk_path(neighbor, path[1:], whole): + yield node + + def walk_paths(self, node, paths, whole=False): + """Given a list of paths, yield the result of walking each path. If + `whole` is true, return every node along each traversal. + + """ + + return { + n for n in itertools.chain(*[ + self.walk_path(node, path, whole=whole) + for path in paths + ]) + } diff --git a/esbuild/graph/common/util.py b/esbuild/graph/common/util.py new file mode 100644 index 00000000..44cb23f9 --- /dev/null +++ b/esbuild/graph/common/util.py @@ -0,0 +1,126 @@ +# -*- coding: utf-8 -*- +""" +esbuild.graph.common.util +---------------------------------- + +Common utilities for things like logging + +""" + +from datadog import statsd + +from progressbar import ( + ProgressBar, + Percentage, + Bar, + ETA, +) + + +def get_file_to_case_paths(cls, file_to_case_paths): + """Given a node, return the paths the lead monotonically up to case""" + + parent_labels = { + link['dst_type'].label + for link in cls._pg_links.values() + } + return ( + path + for path in file_to_case_paths + if path and path[0] in parent_labels + ) + +def reverse_paths(paths, starting_label): + """Reverse the paths and add starting label to end of reversed paths""" + + return [ + list(reversed(l))[1:]+[starting_label] + for l in paths + ] + + +def remove_index_files(files, index_file_extensions): + """Returns a set of files that are not index files""" + + return { + file_ for file_ in files + if not is_index_file(file_, index_file_extensions) + } + + +def is_index_file(node, index_file_extensions): + """Given a node, return whether it is considerend an 'index file' + + :returns: bool + + """ + + # Active index files + if node._dictionary['category'] == 'index_file': + return True + + # Legacy index files + elif node.label == 'file': + for extension in index_file_extensions: + if node._props.get('file_name', '').endswith(extension): + return True + + else: + return False + + +def log_warning(logger, title, text, tags=[], *args, **kwargs): + """Log a warning to logger and statsd""" + + logger.warning("{}: {}".format(title, text)) + statsd.event( + title, + text, + source_type_name="esbuild", + alert_type="warning", + tags=tags, + ) + + +def log_error(logger, title, text, tags=[], *args, **kwargs): + """Log an error to logger and statsd""" + + logger.error("{}: {}".format(title, text)) + statsd.event( + title, + text, + source_type_name="esbuild", + alert_type="error", + tags=tags, + ) + + +def truncate_path(path, label): + """ + Given a path (a list of node labels), "truncate" it from the left + such that it starts with the given label, or return [], e.g.: + + truncate_path(["a", "b", "c"], "a") -> ["b", "c"] + truncate_path(["c", "d"], "b") -> [] + + """ + for i, currlabel in enumerate(path): + if currlabel == label: + return path[i+1:] + return [] + + +def get_pbar(title, maxval): + """Create and initialize a custom progressbar + + :param str title: The text of the progress bar + :param int maxval: The maximumum value of the progress bar + + """ + maxval = maxval or 1 # prevent maxal of 0 + pbar = ProgressBar(widgets=[ + title, Percentage(), ' ', + Bar(marker='#', left='[', right=']'), ' ', + ETA(), ' '], maxval=maxval) + pbar.update(0) + return pbar diff --git a/tests/test_graph_active_builder.py b/tests/test_graph_active_builder.py index cf829e89..f056f7a9 100644 --- a/tests/test_graph_active_builder.py +++ b/tests/test_graph_active_builder.py @@ -25,6 +25,10 @@ subtree_paths_to_file, ) +from esbuild.graph.common.cache import ( + CachedGraph, +) + # Define the number of files that should be loaded as documents N_FILES = 9 @@ -33,12 +37,17 @@ @pytest.fixture(scope='module') -def index(): - builder = ActiveGraphIndexBuilder(_graph) - builder.cache_database() - import ipdb; ipdb.set_trace(); - index = builder.denormalize_all() - return Index._make(index) +def cached_graph(): + options = ActiveGraphIndexBuilder.get_caching_options() + cache = CachedGraph(_graph, options) + cache.cache_database() + return cache + + +@pytest.fixture(scope='module') +def index(cached_graph): + builder = ActiveGraphIndexBuilder(cached_graph) + return Index._make(builder.denormalize_all()) @pytest.fixture diff --git a/tests/test_suite_data.gv.pdf b/tests/test_suite_data.gv.pdf index 22b9a27de44cb21c120cc169ac7926f71b811198..0121a0b652e30d870f4db6009b8450e83baa8445 100644 GIT binary patch delta 16436 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�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

e&XDu0cZgu>Bza1P6CO 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 From e28f74ab56ff62ab0c78c38de416ed9fb4ef2e9a Mon Sep 17 00:00:00 2001 From: Joshua Miller Date: Mon, 17 Oct 2016 21:19:18 -0500 Subject: [PATCH 03/37] wip --- esbuild/graph/common/builder.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/esbuild/graph/common/builder.py b/esbuild/graph/common/builder.py index 9a95d5ed..4e49a445 100644 --- a/esbuild/graph/common/builder.py +++ b/esbuild/graph/common/builder.py @@ -1170,7 +1170,8 @@ def denormalize_projects(self, projects=None): """ if not projects: - projects = self.projects + projects = self.cache.projects + project_docs = [] pbar = util.get_pbar('Denormalizing projects ', len(projects)) for project in projects: From 9a520a19bb984acd00827cc702e11fe64bf769d9 Mon Sep 17 00:00:00 2001 From: Joshua Miller Date: Mon, 17 Oct 2016 21:20:54 -0500 Subject: [PATCH 04/37] test_graph_active_builder passing barring annotations --- tests/test_suite_data.gv.pdf | Bin 46195 -> 46207 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/tests/test_suite_data.gv.pdf b/tests/test_suite_data.gv.pdf index 0121a0b652e30d870f4db6009b8450e83baa8445..857cc270c515b2da46a4f642ea44febb6af19b3c 100644 GIT binary patch delta 18168 zcmV(%K;pmi=mP)f0=Z+}XLD4*ns*}SgmXwX^U(CeDnYi`! z1l~Cl%WZmm8cxqCe`Qc91*Jszw5-J_h_`Wgn+pG>Z3;!+@y`?u}BC;S=h@edjX2yhk5x4{1Kjnf2SWb2A*4O2t0**@g%em z1#tDg8>R%F!4IGy(&Jl|@;ccN)PE4v9}ntp4eGB6>Yu?kp{a2AVx`2gVXFR}srrto z`qruX#;N)zaTAKeVOqAv^-st3!*TtOX_UVYfB_jvWgc;g}CZN_azq=x2!ZTj1`LEjhqtFwW& zVf?p)`9LyN9~j0r?wgr{>RbC}J`!lN;cHQX!7!ptC;EmwfkCr0M+V!EhhjRD^Nx`xO`v!1oSrSn|VQ?e@%_^WB059zQFrgsANar-RuQ{-?U5!9ECePKl4Q3+3dxECsN7<4|P68o`N34 zIefRQe+}H9-5$6vdt=~-Ez03tdF6h$&s3@%3Ftf&xDjr%HZzRR+ZR}qCr{7@R=^#X zr+Nd6p!;sw7|5gwff?B+1Jkl=0#hna8sDkhu_yb4GOWMJ`ZiynE$a(3xBNWN)CnWm z7bud;_XTPz53k86!>ewY7)ZkKm_vc8nbm<1e>@V)>AY;lQ#5Lozw|F?0;c3*dy_q4Sjc zpagVv9!4`s1^1!qQG(nDP_|wh4?Xw$-AaPPJEkORRXIy!&hqNSu>uw>{SX-VhMwNhtr?_A}&e}6lC zFF8C{>fDR&?V8!Q_g;BP=f1h}+%5?wbpH*vtnT{8vu-^1tkt*thiBbFZnl~{>jvez ze|uIJIeY_oRu_3z7kSnV@(s$f$mqM4&1hfyAO6-|cG(4M*It0wb%@v+zuK594kLP`Znzcf0{W!HmclOLQ&*J8_=B~Pd1V0sRo6%jPN6{|y3HoAm_voi6kFJL^-WvS_%7R97Gtjade?{P)%h9Dc zO|2W(jebZ*f?k5(33L+Af55Y8iLM>hkJgNyhVzX8H5v7y^Wln>=xP|ro#+MhD*S#6 zPmSYxJPTinH{q@LC90jaFdRF1^g4J;9^l;!zbWwkYvE0|p&bCj2hn5jdmjA?Ag{&} z)kbZiPSGY>W~Q-&qt}e?8GUB-7ce6%G64L0;WrVjLsy_J=tdaNe{JXxdJeqgYdU^c3hD z5t#V`{2JgHt!NsWf%?&6fb|LmKkh<%&|Y*HVD}a}j^0NjsEqwE&H`@7bMTe;NBAf{ zhW}1clt2aGnF(q$f3*{SN2p`eTeO?@(Q&$(zJR`+-bp{mY-bmd zi_3%MtIJP~_Kw~$`snBpcpDMkhRkUX8V{qLhGxPHUWl$#V7-;#61>lTbP#@r;H{oS zPoZP*ZofyT0O!sC9MlRNoB)X&F5(hyf%ojdop?N`JyY;Zf0&=yxDPMD%kc)h5q}%s z3%~E<-7t;=@H>p3#INGl@vq@`0)Gy_zf&y5QBF#tqLfVa!f!VG7Ep_*rPMNNC3Oq@ z9-#J62dH5h(Jgd0y#Rhg^bz_k`q%Vt>3=eAW*u`C^Hb&+bDTNB{5SI@E3i3s7JHt` zsVb@lRrjg(e{(Ci$GGEYAHeu0Fs85nEkf(5+o^w{jnp`xvzI~Uy+ZZCOl-jW@qGZP z`_a8XAGM&1zXzBpqiXnR;CCIsunK-ijzuG3DI^91exKLlb~zn(o7G}A2}Xlnr`4!= zPQ@}bs7a|Vse68KC^~zF?je}t~?Z=N$0B-br~L*F=4hBGhx zw=?C+new?au@EewQaTmvl7d4&@05bWc+RvwXy4K)^#_MeD(y*1dz;eMLt7N#f?$_( zX=iW<&kuGDbq_Ax+BLs3ox+D@fSx9u0^|T_XvvL-P{)D|AP!ImIiqXHEp>Jcxg==A zF*?$@SV2jLO9vo6j?b6b%%jW~k(e%E3 zZrQC!kRdd+Z=XwcDLd)ZVduss5rA?y-Ii`6b(84aSgHT`txEqdkC58A@#ycM?wx)P zE|@%98V|2I6kMb{M1ps1AjOgfv~^JffDiuqF^qEAkh)|3R-qB*V~C9iQgG`RU>41n ze@=e>&7K8gJ*tTC1tJH@be_YAAt2KVc7TnR>K#VvseOAf{!Ty9_l8lY?=VOidfo-; zVH79mu&fiVhMhzTI;uoyRi%R6@YdaA-hx|$TgNZn8te`(g$ZXON(~2=Z0*m&aAx!^ zgK}n{I3)Lb&NY|x_cy|QlH@*c37o#Qe;@9!eC!TTD_z+UI4PCtC8B+5-?YA=O`V=0 zxw9WY0w{K5YTwWiz^?v&I19!&_NGv8Smqpi=M21ax(beGD|Z1MbQ9d7f9qCq&l!D^ zICNy|R?k*K6P5j8jQ+ht9_tuJ;G2}E}VPQZ$P*K-nl>^T>SqI!i`^pF#8e` zsfW=8u+_sh6>J(aY#+kb3|l{J4%pgY>xL~3+e+A);W|Hi9+F_olY1~9!g*_v1KQPN z_f+~gpVCK;iO}B+=acpJgXiyGgXBB;^C!9xUlj(>yaZ%IX3%e~pb^@Ye?t!BL@sE# zkq7iLA0iqq0_*sje?iz4Q3y1>Fz7l_6oYq2fMiUf6v)pEXrVcfnKhu7)`A{fKc)#a ze)A^(zujvB-I@H=qm7^`eTtXj7pa-l$DpU2Vy$sSV8;p(~1`Auq#dY?wt{FnA> z?Q6PP-7och`hOYr87~#ie-~aeYs_Jb&hj0r*ZK$Bb+#|<#~m9TpExgdWn5RfFZ2kW zE#3z2=e|q)jsANB^??_I4~yRkWkL^1Yr>77V~Svf+yQn74RhRafWqTh6}Tg0FJidy zG}5rlc$%i%Y85vgBNwm!OzfWSOeQCvDoq+GO%}c^O%g^*sI@dwe-chXQJu@1L{khl zksTa9{V%rnUk8Wjch5v%lo(x5-cGGzmjbSI$zGkFq4m7Z!Z12LZPHsT4u_lh3EyLK znJvRuyI=fPqRzD=F_&5AQP$-p7h2 z$U!xQjRL2Fe_Ctgj4HvTve@CBtUcPF7+p5I@=lY^QwBfj)W|pA$x%dt@=9m`Q5?Jy z7ppJSn}iq@E7%=o6E$vf@04%PZnE4xZe!!LH{Czj@&;a1fBtfC?kWF9?9?`7wMW#UJ-$)QK_XS$E9^b6>1^bw+~Q5{><(-V2sE~C*r}7kmnTu{$yT^~$9lN|`E*fd#2V!z-lz~^qI!p>4j~&= zhdCd#SR=HwE<+u{7AVvnRUM{HP!JngDM$nUuEnbd&_LL1s*O=nh*sIG4tw5AlwOV! zL$RnyDAebv4VQ>54?o;0hUB3SuUXP^S^0M_T(f2Fe^sLqFc+%-_FZf!fBL=u{%}i~ zZTjo;BQFh=5AJ^!_h9OY5rShM0^^FX7XTMpCA$W#H(05twcbkUMi%nF3(@~v$o)>T z{to<>m+Z4Fw1OW~HtBUV#qc(k=X6e(Z;Bqqxq~{L-sNyUg|9#&z8?>uF`NfvADj46 ztJzVUfAq!4Gx&>SvO0%gV0N3yYIoSgx)xk#s*Oq^6;~I@Qw#C*OGl2apWuwUXN2)8 z9ox^UPfwgw#d!Uy`Z@Fuay34|3x)*-8x+y6vWtOZ4$BiGW^n9Yf|pt7#nkP_FO6SX z8P=$>+Kdq^ljN;Hx7g{@Xt7p9)5uLbT_%@Pf2+Z)%BosnU~Sg>+%gh9I(m!gDc6(W zy7K{MaC?2;?6DKVm#1KM-Ob0GZlKxLlO`BSg|JAAATq}a?iZA~_c8(>;q)-eYK>0I z8tFQ$*1^;=0u+c$uTT<7XQy^`fyZ@Z=!61VaJ~knmcn8U&?zl8<4dq=*Qy(5Ws}L8 ze?Q;&&>Md!-+*78Ke^hy>dfyQ_-efPq3_+ZxUfe3@&32&zOVdx`KnC6uKXuJX@E`t z=wInUb~#9d9dc>BYc5A|VS6~i6}et+Ik%i&&t1hoqNb+z^R zw-2`7yrnSkzTPQNyN16zaLLR}T_Aq^*1LY(6`MZ4ab@|f^5<7A5+grZ^Yp3}f75Qn zl)Lfvt5&X=mO7ui^U#BrESQ!lCJM`TKU4l-e3hF7bAaw0fIlw*?o%M6ua^T?(3sV$ z7&S%f5yorHdOeNxNJldoglQGT2i5`4*Wo)3YG_uY(+p$3tVZ{#bIk7;iW$cBj|Ww< zYL|*uJxOUm#_IqyMuUPr1E&T`eYoGVV8#_miFxy5Z(BD3D_4VaP@T}{VIc^*Ml)i?&24w$ha_j~V zuH&sX&_@yu)*7wPugU?SU4<& zLx=!!L;*Jn7KI`>1C~UBe-#ct2E>qn0TRsk<>8vOkCs2b>)UoMPtnwI{8&)(3X_?z zt-N8@eG@m#?3qx0;jarzi<9ZcuYL7~~7YDP>fs-bMdlVIZ5eL#a zv!{m2zs1gf;RbfYf5CC%H#u9X2G=kcoU2k*)IZ@T^Ri?L8XjwfIC=8AmT8#||Gwgjx2YWh1Fw20{Ko|x+f59wJQcA5vGpevtK&MQS zAk&!Q0<0Az#Q+|_HY{Ng1i3?`6No@fa+bjO-dFCbgLSa`g(b8$O z66S6Ty9l&zC(7fb{P0%pZr=|74)KoU?diKRJM#DYA4)!uzCZuBw4P1d(^QgaW*SwE z)r~bBs&S6)e^^)bxSBci0CO?3jJ=9ks~gl`W?$>L%(*UdGjkJrz2lC^LHZzbh<#lA zP5etH5NE>9I-1rnnwU%P3YVD1Xel;_o$H$Go||9JEN7Rymb;hdg-$*nb+U}nrc_$< zt^ljumC_qmgdV3>pu{flI06#M+B(|`?;(E0vsnyLe>84yT`l0!z)7NHkW$ezOo{|@ zRB))KD&rFcs~Y%}Ce0IM0sX?_x78t2&l-2xL$; z!oZTFF$0hn=otmF15z1w9887Qh29#;{`%v$uvMW4uqE010ge>J#YJ3_AEu48 z;G$iO*=QC#0Z%YVCz*t*NEex+suU;%e`jfCIc}zJX14G*sK2HEmf>5*ZwWUCZVui} z-_2~-Z#Qf=ZWrzj+#L*e>N^b-2jNcSu-h@^bi(FxVa7xMSS5IjdXFKl5#a&Gpxs3| zX$0)*3e2m6yh@ca!-;B*CSisvRW8~N?pu*HV3%E^Vw^z?$ptBga~RK(b!u5ufAe(E zXrOtiO%1};fL{O!-2=m+DK!dZPq|$qBTm9iO2AJ_ZenDCq=MNSBNHNO$0QZhPDNxT ziNJz?C#ka#AjuNP9VRW(*etLcj+QnHB~B;^lc|UEialfWj=l+j?4Mxf1Z)Q&#ASVXN`O^HBja5!7<7})s7q+`R|DO!avX_ zPhY;Spov6yN7^{C>V=>6yKAjFRRksr_?QIlgr^mr8v&dCb$RLyp6mTo1KmT<^-S|0 z!Y|^t@jJ8)P=TNeLP#H!x0`r`FYvw>Z4}L!A-$ugLJSqr%srJVT#^cn+Jj*X6l<2o>LM|ww6Hi1r5Qf5R zq$(T(Ga%1ajDT33Si_v-e=$H8A|h-^Q4?*Z0#$zVA4jq-cWLFwb61Zae>K(eB^H+y z*WB{*2bVoEvY2|d^Saw-JS6*{pK#@4k8Z?esxA=WTG!IIu5MFBfAG`q_9nfdowxpF zPL}#}pmfjUvShC=*MQ@OLiy1TAeOO6@vJ;5yMN>T*zuv0?sqP8e^PPY?qEHtjWX{M zIc^xY$syRGc1P`;5sX!Ur9_)E9(6bz;1=w3JnQ&{g9dFtwLfZ{85pM6z0rumT*?C{ z0DOdf10X9pAaXZ<;&z?_jB_`ibh?4Lk1-jqH>5ZDB4X6!H5QOQ1cl%?7my*SD*$^@ zjKneaLKNvj-XbZ&e;>30l&=AyvV;8jtL*?2VXa1o4X!&h0tPf92&W@hfcFC`v$6=g&^(}xC z@qcUpoHT%5a+h55k_SJ?5A(zBgPwo#Y&~xljh=8kY!N+3{wXtm!L@CALMk5MrZcZ849AyomZ zT~M$-s(?6;<{U_ppgt0w8wQ{#{)8xK4K~wP$Q5)jrV9I&z)-E8^p|`7>*#~!&$_D1 zS6|xMzJ`ipf5%Vp`5QJ)J@5M;jl6VmaNcd;xNq9I#h*X@=k>bcI{Ma2Wj=cT{pHzr zl|P?X3V>@(u_Kt504Bs2_lmq?No+87eT+7|to0Z*SaY?(ccD612;? zPTi|nhoV!XRCJiq988)635F)XOjeE2?3V+lPMs<#$ks|K0^pOvNkYD$o&&|=3IP-T zh=eZ&@X61U$x1!8ONfk^;7qM4qBe;ime6`%pQ#=!JH!1aF*ERYtC^-Tb$ z4z6fh_elAZgagOV!Rei@btBJ3^sU#^msbFEORqO^4nXqiRyFYnQmA_LLv}atDdOpU zR`z^M;W#f{>GA(KB zwPXErFO=WHRqsX?r^kmoR#TdZuB!6Re;<|KeC@-7FX8bbFtbpwJZ;DLP2d`MsQgj+ zIfKzDh48q+MlKp~}v2l{X+4{RZ-7!ipdem_OSzA0L zP4EQbAsSFGc^35q(PNEEZqeh9OHt8N1*PPsnMl$l=oyAL8dBj%#BZ~zc`8{IfAI5y zlyHI5kU5yvN5^PZQ9KFS5sl@n0;A9@m_?xF6A~r5I{71Rv#;>X1}Xh8)#?PSbMyuuKC9ca{H@J4V?spw@slIw$_u08~e>v>5fwo&2 zJ@4FO&A8!>-8^yzol~8(lduM_^2&s-dOhd(Dp&{L!Us+Y3J_tV%H({LS)QE>Kh6gg z_NZ`2s$=yeN6eA$#-<~4Y8Rj0_Z2gYs#-2Q6A#5$nwoRC{QYx0Q1uCnB?45w>|+sg zYPDA7b!i>mgtn*!3&?wsfA?tsUg5Wpm24#xa}R7IXBP7H-5Dl-NI z|M}+vcz&R2&bnWAJ5j5nG~yt0ICcWd2}uT2W>!cFJkglJ)A!Y+e}Z@GEO5rWzF^jy z6t!7&T+`EiHQs@b;}`IqYuek_fP&XNa>_e0QXO1X4n*|*KcwYV9jfT*zccD6-?4HG zOEq2B(RZF+!(4FY7Z2t|9WY6d$D^OH4+8AK+Cg{9?Z0v2KG#y$``S+ppV~h1sY ziq1hGps+76e-ivIpH`13T?9w9KEo_bxuDQ{HM1b}NzeL9wY?UNpSfOEs{`CT#B)Ir zD{gawPiV{-0Qv$QuMV=J#?EhOU1{(d}gwC+%@#&e=9oG(O2$&<0-m)^STldy5NT> zZ)bNv+)E1@-f!h>#QA{s6~lAFbM{xlKaad?cvE=O{%-i)i0&2ZE3w~L-;XiVc-i9- zy$(KOq^T!x2!*guhF#eqiIhX4Sgm&fJ2PO}X?fQ23(Kg5wGeZmN;?yL5$xWogd%o9 zBR)YOe+QW3-f#?D>8SNfh%gE7fvMnjDi&8M6hroCED{UHAUG7&M@ee^_|tjqA6S|8e!uq6cR_P##^jY`@0+ z@W5kuVfj^@R#Mig%CDB6!aXk@-2X!PVEJDMpU>~_t+GbIdwGP_O zlUam-7#dI}&1`ovDo2Eks_cO9jFSVbeis%Scr-qpMr;p&GmC+q7r%Kg>Ls;TPTsf>s81l$|t^XwPe zDf{lIB_7dh7$%S@SZF4bQOmWSx?#LbHX={GUeH8BaSvB;dEC%<(ChJg`oPZ4%f^C7 z$R+=r90dnevA!=fjIVwi2|0lhe~Jy+V{Z;@IC;Ve4hn$pqzxyXr<`tZk7i+yaNME* zJ3upvwM`;V&7Tht9rave^%`Y5YJ+Lk95#ezA$0<#f=xpaG{dfBjLbseh(XU+X=dR> zT&+>1m{~|P1;DXEXa}gL!jy>eLhMe6e-n+CxGNMIA<>DNvpOzVP{aY~f3OFz64)Xx zKj`5k8h^XC`^tk0Z|%w6v1dwl_G=G!zhH>^_^Nbu&HES6+>pyHIq*5_X}g# z#iW~I3Cz7)r{8+@s>Kts7p$zwFSzWU*Sf-DdEyKAF6x`oP;6PXbavkryWiY7gE+Q9Cg#<(Y?JRZaj0D9SX!qfdu;h=Zmj%gc5T z<*=9_*@fp#dX*&uu_e8ZcL81Oqk8c$=4AuNC(HrUJkw6o9us4Nu6?N2aTuI(&McUq z5cMjZI(5#=uV_pPIiUASip_}!;7>UDISI-WBQpu=0PvYgNLYbRf1J5qTOD4tZw+XF zk6b6OdHAY84clA3@4iK+KOw4LMALpfgBIRT#;6|sgj)w=Y=F$kJ93aciv(WTcg z%IFc|TFDb0^b|Y|@j5vbai>tt@aX0H)iu>YsO6dNOgfmW_E)FOYPF^+olcqEZjUyT zNkHwYtEovqKVMf<%`*+TOxmT@sMMaSh`TOV1<9`@-&Ir7e-H@+x29^UGih}rgySQ_ zxcfj5xv~36aFA|7YW$q638IEg4OD}x*f@;;uwT6Nd?h?T;C4+KaXUw#9&w%x(<=^C z(C0uYSA2U=gOa;>QYLAD$PBv~oTvY@L4r2G-+=PSHEyTkNc}%6IPj%{Q)wt{wpPe}@&T50C&`KqpePB4P$YhZ=*NAhbm^CFtX5j+SCHmb93HK0Mm&&ShY$GTPQ-t2bf4E-?)*Tf1j0aK1mIp`96La{}#tLv(XA| zp;1JSjxGU@tyea{$^r^1&XDypmUm);_lEP(5^`oQ#OH6M4}gr5Q5)9D z7k(N&9i_Nfw~Eq9cWdr0KBRd_`=I_Q^(*REv#;jfQ@@uxUj4cHWX?F7PgPerya8(f z<&8#ce;i+vsV`Qij2fh}^45HW%e2&M`IcsF8`oBh3EFI1m0Z0(k*(TOMO6(`NY->X zW1h}XJJTt{@|wLJ?L^%;H9{izrH^6$MoK4${tCKACDj4ClyJx~Xebk`@Xe-{Rw=G? zV2+CDqpGMmiVaK@aV?A=*}@J#s2Y~2;K#8zf2~7NjFG{}w(@>tidp^V*e57;iVi{; z=vlWg_}G;Rudvc^p*~V^|0+m8Ji|)d2^cF#L}EJ-9~40c=#EvYI!yJh?cG+2<=WSm z(Ra_s7HeolK9kWzY`%2vu^&Iz72)*>hd&aGG&FWL(-Z6GPCsuW-au7FGySXQCcP7i ze=8Q0E}C^=yuWX}WUEdV$zH4LGx67*u-I;qtG>`-l@8yn#}bc^+omEf-X^Ic9AvJlY+4$LEn3dA$fWgm8ipwdB!dd4 z%36=uunqEoE5T#noiHPnXdlVsItzTHf8@|8Q{eOlbwW_*k7BO?ML;h`vCrrMtW?xG z#TB}Gzyk4#Jiux!Moa?dQ6=9-aled(_)OfILmcIaB@VEWk4)oHu5=V_O#mur^Umf5dVuh(2@yV9t(STEDJ?JFHiSiP4<-tr& zs)H=2pjf}=`;Tp3IxW-aEw--TdGBAa>g5!@=h{hPF_+2J*=;Y~f5%@sW3xph zuYQ4H*#g0jYJkm2b`Y{O8_~P+$~)r^#b1s8EcIdPR7!g|Uh>_{TMY&}IWa*=y!JRVRpZreGx>v#sXnj&Hn9d0Zx{y?iq&Mn%4cgE z8FSi%Yx8NYu_YE0wIL>Jj>$@90yY%&*^xCD-npkSjb z&SIO&2nMf0rc_<6Id85X%lsmdQ7Y3Mk9hJrb6|RUPDqHTC`?hoF0Eawy6O8|Lt^~= zhkrHl_}ck5wQsz6$M@*HL0bg3G-oJUwCUVB)<7*Qu5UW?i?&)!e~DDCNqtqbJB_)= zeuE2V9y~vRAG>bFZ-2D=4DjCg=qIp>=V9<=kxbj)$OFsx<+@eoi)~kN>-j5n8%)=j zH&{2=&KSNl>Sys6^7BncnU~COG9Rn|VC0)g8i*6zCX`x3t3a`Y`0_Yf<@GM|S-9I& zKU7hwHoey81cBlce|`b}e}cUM`dx^s;k^NW1$zg~MbK0$_**fR2b_>7Rbj7Ck0EiD z!Gl;^#2vMo6^;tw0zY;+SpywKc9R#{7z)OyQf2|Hh_n3kY-q?P5-SA6^&?Ue=v^0&?SyRpP1#c0Kmhr&ODY?^u=Re3>1ZmV-U1QVp~;s zAJD8*I0|;}e>tC$RF{YR10`p!Lcc`C=2SjR@~0FvGQPaykw=o#-|f387xGp4OonJ^ zqQ`jppUu~feCB1lR#De={9xr9-A!VxlycjAz45k_9U~jT*G^XBF{r-WPCp0y%z}Dg z<<@M7z%Cfy-qUeY`;8qBdssHk7StW?j$+4h`r?KMf2pb-Cg{YtDf!v%po^ngiiX*6|+PB-7jTB>F|tB!Je~kv+uGqkXk#sx4$oYY(z;40h8v~nPD zI}N@!e=tZeDy!t*jiFY>oecR|kT*iWXeQEAQK`TW1^*;>$gCt)DP~I(wn=Agl~~1i z$%8+j;$;EjrWN!qayAe-+$CB`J+kNNpFMr$1Fz4l{cdD>$iC32%jRNBo_Kit&@|gD zi|#SA#`N?qSDSBMccua3^Y19{JaFHUd~drhf8&UEt^OiXTCjRy#4>mRU;dlCc4h}? zUl>+&8Q502o{HT)|FU0p(bK8|jkRl@RWA$#jT&F}o*z7Q{rGTKXOqrs3dAG*i>?0L z<@5e)pt|SE=cr!5S2N)2MV?(qr{$&)!QWgk zf9!7c`h!xk)te1UXW4E-N+uJM+eE8kIYzJQuDC`xI-R#b&Jq%d|&WI!C2U7@$8R(dB)iD<; zF^E8zw_-;{m@694IdiF!t5ZRI^Ypy0e?e>0r>=F)r&_D~F8pCruzF&7%Iuo9Ig@Xz zomC#^)izy1A8Dwgsjxo6`?-<3dqSlxJ(rc2E|)c4udeYDyaT?DVJcfLZO{>N02u~! zPZ-k8fQ?ue}jz$ zg6|7PLg`T@1ORxeSca{W6n9ER;s{>=4}(ngugJQNRvdha(~qkos790-g}fgurIO9f z$y906iUzeYr?u52_jGxAs<5E!X6sv;m7}Lkn!3yI`)#fSV+a_EJ{`x8)U0VF9~gn* zjBYKul3-0k1|f*;M?Q#g8r6SE>>7Kr689g&t*BqXzU#d9XX&7aX+R zV0*y!Y4~4ZjtNGCQL#Q)5c{qDxr>6!b9dP^VklHJTSJn~Duv|G46|5mwN>YAIcs%w z4wh*Ahf8pR%aW6 z+T%w+I1qwrEE1jN#0juXz~OV0M8)90Iji{Klo$laic=@gkOR;Q{Twg2lWvGb@DPjm zW++0TBL$NnpUo5j{5l&%Gh)asCH@COanN}-I>F3u&ZRA0)0~TXe^RjE0o(kxbR*t< z>6V{19sbU?Y2^;d1Ob@xD|!F;vgqY%X3(FGi&B)=>2Vra^_j;{d4f8Jj`n)F-o5pI z8D7u1y%g3Nv=$w{v;3Vd5YK*qJ#oMp*sH-u1M4eni0(jMM=)#;nsvvSMy*%3&1{0; z8l3E~YrqSG4w%eYf0`i_1>P25GzvKZ04izrW298!9b@EEUmzn^h^K0xU2APNh_21g zaCGT{ve&CF&Y<6DcU7rWVz{KUo}M;4&jFQSlJlXer5}Wq?EjLz^{(0=WeWb-Kut+Z zDN#a`FexyZZY`ucyoqPvyD}jpgSF>HC78vDA*K;|CkMmfe@1USC>2`0O+jgVqjyqJ z(goS6Fr?dz9pgO(d3;ZYT&PcnJyw>{bxpPyYr0w-H7$XF!^lmZRBB4ZHB$*A(E`7mg@`Iwp-=bWvWMpp2xcxOKg0WRiHA3K;?umcxrIK3E(-`AaEjo zP(mzEiB%B1e<6$+SaXGD32#m&O&Rb|jm2w-ko%fu3wnnS{IkRkbr7ahu}8n+#suP^ zYgK>^TpO;fOhTncoa~Or(l(o+C$^7esYTl+Uep}4O(@J;w7WjgI=$RHyI_l4+$Klr zi|3c?=G9uo70rX`y8d#}%~^c2DRx4JVI`-&Q)AdXf2XTE+SVIx`PPJ8YWTq!wg)*8plXkmxo!4XM-Hi)7>POz6*ofVPpToS;AJRWjR*O9@_q*Ja+|=!c z2Miz>1ENq9$Y;e?k&U!^#bAgaV?G%6HhP0W32dJlGKCeaG-lEfuZ5wxyxEv&am0*V zzD5jce`>i}$f>AhJdpB(9skZ5b*~479!mvCE{%$(*b^U;%xeA z0@wkjA{=9Jr#tS9g2L;Lxe{Lq$AK}?cow}|F`1SBG#y``4ICL))LEL;7DM8$3po1x z+Q~CJ8!m3_EYBL>D4*BV9IBVQ%DwnKue$Dhf52ilP_m?}324;Y&kI(^CO%(I_sH1m z)ihs-A31Mz+)+33dQUaw1xV7UcJ%k4Gd>J5lC0;uO-{Y2{zy&TF5G3`B|KvPLc`jT zm2o&`X=Vy+Bk#<+D9)VcwJuwyOADFf)FF?t(+H6YVl8;wV}_c!s2B^7d7*$Kg&g{b ze-0a?$U)np*rbM*g@cv>IiuLlKp|+%QTXHx6aMA+Db2>n19cZG3?7drIb z{PA$6!&~!#kZf_x;ewV3CzM_IPL zX3o5=Fa7yoLqe`^UsX1(>-hDN;X`v%W%bA-s?PEBk%>vLUIVyOt=ilkZ20Wh%jG8w zwubWIB^e%)KM8!R0luGr4I+T{fBJ?zOOtdb3rTuM>Y>cx%(2XGs82FqrnpHd+`vaV zyy6ETk3yi3@eGT3th7hv$ax}FV${mhjNo!=@;MH|&@EM3F=$Z5B3ZW#YZ-t(57p>9 zccyWgpq-+;D*ge0EwRMD0a#e#L6{|h@!2H3WR|m-0g%R|K8mziDAXpEe;?d#h7>qn zbQujm+@b-hC4LtOIl|wVVjCVy_fhDV_yEknO+hk4g85ipfWkS){CePtq0lrbXLY7G zd}s5G8|T(a<5sDGds=)m%HICj-T9fzHoT7U&sPW*cf5cfn39_M*&Tb2)14Mwyq&=e zqdhIxxnsOn#EpybhAw~ge;;Qnh7vP*gTjYsH{kRaqfdnR8F9G7KgNQF} zkZA=E%xyv_;HQ(}a0rBP!s@dGH~DbTm-A7+9X=uE;6PYy0{?r`5(`(%fdhMh0wFhV zKoLhr2MA0joj7)KHMjwk#WD&+&mk*5D{&N|K@gE>{Q#A-5@*a|f2Clk)n2fP>hnvH zYK>?vUg4;z<7oMEIWJd7qLb{>g;NL07Ll)>il1LJi)BP>mD=Le2>10bZq6hcx>uLV z&F6JcAP5MqEgd~c{fypARuE%a7A?qv?NmZv)GyU7)34XA*KN^3j(g5q{RXfG-Oabvpj-^cY9Yk;H(5ZjOO3mXM~t+w8`XkG3qUvcrgPxLNzna(7Y-gBSnX6S zT}Y(;N^V!O(LNeb($Ol(w9o}HzmJskS`z$I_<%Q_2#T;=f0a`ucs~xBLVm=>Sw9km zfa014JguZCTk>ZEdf*()fI>*D65>udn{5l+6QX$)_aT`k2`?8NvF^>ivuj!}y=vXA z^>x?qW;~0pwp^t)VNZy%Qbm7AC2K{^IIhL0l{KO^ zEc;<;IF+?}oU$op1+(4uf_9Tnh3Q$;vz6VWkqVt#jIif(qtPm}2NC69WBP3R4nb zL4`#rOJW8T^rX3d*DX>!Qkga1tbU}RHgVq)5rg6LF^e-%gM&OGfk8m;P(TD5yxtklxHjpC+y zOq^Focv1vl_By>AN$7t0f|xdDD`*S0K7O_^+cewJ@9Xz3bqQhx%~?N zX7y(K7XMx7F6`hrUac;g0fBjko#SRGsbQQNVqvaONU+e@3xQpiHo`+fG ze>wb|MERh3aNITtgR1@Fz~C9D!&H2KaKx#w{1=I)1{q&O0*objeJ$4ulLRI(E<8kR zjs@xfT9_ad*iuS34-eNS)!Nq&=p7L|#4W0miSloG$YL|_<<}xrt{lBPpt6PppLgUm zensrD#7t^B5MYWIjpQr_hlzTxKWJ7df1gFbsA}|c_B#NdMuYm)v&ajjxhzQKo=NQO`SWJE1J_ekJsa^b6agNr92OIENQ7` zm}@+Ba7H>k!yF2Up>(dU#seob*n4w!85?$ zNblQ3Qh+n>YXFCc>CvM};V2~93H(toZo$AMEg)l(Jp!=)Y6c)GnkVQ=CLjutQl$b$ zHkN8e67M{?0A{YzMGu!6_1Z)Ge{|kVs_Y8-%10QLN=N;n{7;HwbyWGS>R=YH$y6tt zku?XXq}7_w;NA3foI7Sq`^yo$&pX!P}z}Ru^iODU!UY)5?u-3 z>b8OM34EQ-x-yxTn6Y^TRR?&(9jFNl^5H*n7(VfZ$%ip;g33}kg`DX(8;Bal8OtTq zV4`KJ8jZNIbs`diQu}ag7Y(HnTNFh@YN<#{h-FaZgeKOx1d*VsJxZl^TI5D-MQ6y^ z>oSxvrS!Vf`FQ8UeLpn#C`q0wTf({hf6*CCeVeMMpaN}&;Fa(#wnmqfQaV;6x_eJu+wznn~jd+ zs((Lg$iW#nXW8Ahi=RX2zp7WcC?M8iU`Ubk+Su$wY^xc@ZNOWKF+7Z5x~`PJrgXaL zG8$Noo`Md|A~9IL{h~T5C0P4|K~(GrnFwRqY;J z%Q!xL;hIt`RLNlt)GLj|R%=r{1IP`pOphDD1swU`E(Q6S-g!SpbRBbj@=_pf#XW87 zDf_On;>Yfwym*#TOkYL>d6T%%+O~;m#axU^-yL;nr;4Ex*;xO2tc;dN{1gR>g^y&J z%P|JIsvP+(cVXsqN)?-9#4_So`egg`xNAJ{MwL$2mHa~~TC^>FNI^GO1-r9L^q$YY z&j=-%+A(8@v(dIqo^?~vuL+&)Bk@rN3t>aEtX^Fl!yzIqRon^6bv<^5VyR2DyK=ao%g7@V_^j?3i8{QK2`rZ=cd1BOuiW^SwUPp} z@s8@CS->RiKx&^AUirHUWsi#E22TB~mu&gYUJDv{MZyyee1Vg}y~qDnk|@&HRUVFhBenm0=U9HBXW;)~R zn+oZ(V!aJ{2;nRtcrRw6rDlhC8FK9Nu&Y@oSwb&1B6^NWc`XIvNMvqEp(G2#B7dFR z0N@VcUg-dpu9Q`y?Rjf+{S@ITy=1iEYV6w^ilnqXr41&S-$7UtY7$2>)y~dUCk^f~ ztOwC;l(L${-|9(T4~5jJ&o7qm-np*T5_O0#yuntAdq>Ev6||IaZt^CxEx>G&ngF;^ zj^i6+6lM7RN;iV24!!-48`KR9_mcxFn)pTv32NNYw|H=yeo}-_q^x~h#O+I!1IeGr zghMh!9T)p=eB+*%Y`s!6-_KWOJv2WN*`c`Nax%0r zTrYEtFJ@U9o0{Ye6dvW|lqIc#CC^W$h2Fxs>yPQ^1IYH^IH(iID(`LoAKx>said^} zV=wU6Gzjy;#IDdy@q?6smxJeafGr{2CqJTnLTq!%u+8&Gzqkt5S42@}&RJhSsEpzL z%iCbB!SL=o!$xA0TGT7}qFZcV-=HnJliVZOL*91Q>); zzA$V5IZ%zQ!JFLNs8}@VbUN2PyI=7tcmUNkyu*WRWWS!>*$V zv1r#-esn=`--8R7kmVByS%DwVa=cj0FPE_XcubFYBiM0gf4b4Zo(53YX>BU98 zy&tzD?^uu=6LeW@2b&XdDl1_k@Cd&tVUa-wc<73dyzY{`!FgRFb7s-l(mY{)6cRl( zg=r4F_vTFUWAmFNKzM9e0x>>3IOYq*g+u|25g-^y{!c=|U`V=mTb?u=1~;RN+p51Z zMYN|s{Yui?91engIZ!MJ@FyUUh%dwcbtcHaIuz?_J1p&+aPOeKmsv1o|qgTjt3x+rl#fq2*lCD3GiRp CkPkTk delta 18132 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 c3#7%7ugCp*JuDoEL|LHFKwVvD9~a=i0W- Date: Mon, 17 Oct 2016 21:22:22 -0500 Subject: [PATCH 05/37] test_graph_active_builder passing barring annotations --- esbuild/graph/common/builder.py | 2 -- esbuild/graph/common/cache.py | 3 ++- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/esbuild/graph/common/builder.py b/esbuild/graph/common/builder.py index 4e49a445..f7652b8b 100644 --- a/esbuild/graph/common/builder.py +++ b/esbuild/graph/common/builder.py @@ -15,9 +15,7 @@ from psqlgraph import Node, Edge from sqlalchemy.orm import joinedload -import itertools import logging -import networkx as nx import random import re diff --git a/esbuild/graph/common/cache.py b/esbuild/graph/common/cache.py index 336f09e8..49e1e652 100644 --- a/esbuild/graph/common/cache.py +++ b/esbuild/graph/common/cache.py @@ -12,6 +12,7 @@ import itertools import networkx as nx +from cdisutils.log import get_logger from gdcdatamodel import models as md from psqlgraph import Edge, Node from sqlalchemy.orm import joinedload @@ -20,7 +21,7 @@ util, ) -logger = logging.getLogger(__name__) +logger = get_logger(__name__) logger.setLevel(logging.INFO) From d25df89830afb43e343fa3b0b7bef8f759ed6713 Mon Sep 17 00:00:00 2001 From: Joshua Miller Date: Mon, 17 Oct 2016 21:43:04 -0500 Subject: [PATCH 06/37] wip --- esbuild/graph/common/builder.py | 1 + esbuild/graph/common/cache.py | 45 ++++++++++++++++++++++---------- tests/test_suite_data.gv.pdf | Bin 46207 -> 46204 bytes 3 files changed, 32 insertions(+), 14 deletions(-) diff --git a/esbuild/graph/common/builder.py b/esbuild/graph/common/builder.py index f7652b8b..09077ded 100644 --- a/esbuild/graph/common/builder.py +++ b/esbuild/graph/common/builder.py @@ -252,6 +252,7 @@ def get_caching_options(cls): omitted_projects=cls.omitted_projects, index_file_extensions=cls.index_file_extensions, possible_associated_entites=cls.possible_associated_entites, + supplement_regexes=cls.supplement_regexes, ) @staticmethod diff --git a/esbuild/graph/common/cache.py b/esbuild/graph/common/cache.py index 49e1e652..fb5db03a 100644 --- a/esbuild/graph/common/cache.py +++ b/esbuild/graph/common/cache.py @@ -12,6 +12,7 @@ import itertools import networkx as nx +from collections import namedtuple from cdisutils.log import get_logger from gdcdatamodel import models as md from psqlgraph import Edge, Node @@ -41,6 +42,7 @@ def __init__( omitted_projects, index_file_extensions, possible_associated_entites, + supplement_regexes, ): """Options required to cache information to SharedGraph object @@ -69,6 +71,7 @@ def __init__( self.omitted_projects = omitted_projects self.index_file_extensions = index_file_extensions self.possible_associated_entites = possible_associated_entites + self.supplement_regexes = supplement_regexes self.file_to_case_paths = util.reverse_paths( self.case_to_file_paths, 'case') @@ -266,31 +269,45 @@ def cache_database(self): 'Caching Database: ', self.psqlgraph_driver.edges().count()) - for e in self.iter_database_edges(): + for edge in self.iter_database_edges(): pbar.update(pbar.currval+1) - triple = (e.src.label, e.label, e.dst.label) + + src, dst = edge.src, edge.dst + triple = (src.label, edge.label, dst.label) + needs_differentiation = ( triple in self.caching_options.differentiated_edges ) + if triple == ("file", "data_from", "file"): # for files that are "data_from" other files, the # centers and aliquots of the source files count # as neighbors of the dst files - for center in e.src.centers: - self.graph.add_edge(e.dst, center) - for aliquot in e.src.aliquots: - self.graph.add_edge(e.dst, aliquot) - if e.label == 'relates_to' and e.__dst_class__ == 'Case': + for center in edge.src.centers: + self.graph.add_edge(dst, center) + for aliquot in edge.src.aliquots: + self.graph.add_edge(dst, aliquot) + + if edge.label == 'relates_to' and edge.__dst_class__ == 'Case': pass - elif needs_differentiation and e._props: + + elif needs_differentiation and edge._props: self.graph.add_edge( - e.src, e.dst, label=e.label, props=e._props) - elif needs_differentiation and not e._props: - self.graph.add_edge(e.src, e.dst, label=e.label) - elif e._props: - self.graph.add_edge(e.src, e.dst, props=e._props) + src, + dst, + label=edge.label, + props=edge._props + ) + + elif needs_differentiation and not edge._props: + self.graph.add_edge(src, dst, label=edge.label) + + elif edge._props: + self.graph.add_edge(src, dst, props=edge._props) + else: - self.graph.add_edge(e.src, e.dst) + self.graph.add_edge(src, dst) + pbar.finish() # Prune graph diff --git a/tests/test_suite_data.gv.pdf b/tests/test_suite_data.gv.pdf index 857cc270c515b2da46a4f642ea44febb6af19b3c..7ff20f2196ec3c9888ca438ca5ea4adaff4aaa4d 100644 GIT binary patch delta 18123 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

McG>mR7V|L0 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 Date: Tue, 18 Oct 2016 08:12:19 -0500 Subject: [PATCH 07/37] active: all but annotations passing --- esbuild/graph/common/builder.py | 64 ++++++++++++++--------------- esbuild/graph/common/cache.py | 7 ++-- tests/test_graph_active_builder.py | 46 +++++++++++---------- tests/test_suite_data.gv.pdf | Bin 46204 -> 46205 bytes 4 files changed, 60 insertions(+), 57 deletions(-) diff --git a/esbuild/graph/common/builder.py b/esbuild/graph/common/builder.py index 09077ded..1b57fedb 100644 --- a/esbuild/graph/common/builder.py +++ b/esbuild/graph/common/builder.py @@ -1131,6 +1131,37 @@ def denormalize_project(self, p): return doc + def is_node_hidden(self, node): + """Return True if the node should be traversed (and therefore must + remain in the cache) but should not appear in any documents + + """ + + # Hide all submitted_* node types from indices + if node.label.startswith('submitted_'): + return True + + if node.label == 'archive': + return True + + return False + + @staticmethod + def node_labels_by_category(categories): + """Returns an iterator of node labels that are files + + """ + + categories = ( + tuple(categories) if hasattr(categories, '__iter__') + else (categories,) + ) + + return [ + n.label for n in Node.get_subclasses() + if n._dictionary['category'] in categories + ] + ################################################################### # Topmost denorm functions ################################################################### @@ -1289,7 +1320,7 @@ def validate_annotations(self, ann_docs): ) def verify_data_category_count(self, case): - for data_category in self.existing_data_types.keys(): + for data_category in self.cache.existing_data_types.keys(): calc = len([ f for f in case['files'] if f.get('data_category') == data_category @@ -1349,34 +1380,3 @@ def validate_case(self, node, case): # Check for keys that are in the doc but not in the mapping self.validate_against_mapping(case, self.case_es_mapping) - - def is_node_hidden(self, node): - """Return True if the node should be traversed (and therefore must - remain in the cache) but should not appear in any documents - - """ - - # Hide all submitted_* node types from indices - if node.label.startswith('submitted_'): - return True - - if node.label == 'archive': - return True - - return False - - @staticmethod - def node_labels_by_category(categories): - """Returns an iterator of node labels that are files - - """ - - categories = ( - tuple(categories) if hasattr(categories, '__iter__') - else (categories,) - ) - - return [ - n.label for n in Node.get_subclasses() - if n._dictionary['category'] in categories - ] diff --git a/esbuild/graph/common/cache.py b/esbuild/graph/common/cache.py index fb5db03a..5b4fef6f 100644 --- a/esbuild/graph/common/cache.py +++ b/esbuild/graph/common/cache.py @@ -263,7 +263,7 @@ def cache_database(self): """ - with self.psqlgraph_driver.session_scope(): + with self.psqlgraph_driver.session_scope() as session: pbar = util.get_pbar( 'Caching Database: ', @@ -273,8 +273,8 @@ def cache_database(self): pbar.update(pbar.currval+1) src, dst = edge.src, edge.dst - triple = (src.label, edge.label, dst.label) + triple = (src.label, edge.label, dst.label) needs_differentiation = ( triple in self.caching_options.differentiated_edges ) @@ -308,6 +308,7 @@ def cache_database(self): else: self.graph.add_edge(src, dst) + session.expunge_all() pbar.finish() # Prune graph @@ -569,7 +570,7 @@ def is_old_supplement_file(self, node): node.label == 'file' and any( p.match(node._props.get('file_name', '')) - for p in self.supplement_regexes + for p in self.caching_options.supplement_regexes ) ) diff --git a/tests/test_graph_active_builder.py b/tests/test_graph_active_builder.py index f056f7a9..62db058b 100644 --- a/tests/test_graph_active_builder.py +++ b/tests/test_graph_active_builder.py @@ -50,16 +50,9 @@ def index(cached_graph): return Index._make(builder.denormalize_all()) -@pytest.fixture -def cached_builder(scope='module'): - builder = ActiveGraphIndexBuilder(_graph) - builder.cache_database() - return builder - - -@pytest.fixture() -def builder(): - return ActiveGraphIndexBuilder(_graph) +@pytest.fixture(scope='module') +def builder(cached_graph): + return ActiveGraphIndexBuilder(cached_graph) @pytest.fixture @@ -343,6 +336,12 @@ def test_file_to_read_group_paths(label, path): assert path in ActiveGraphIndexBuilder.file_to_read_group_paths[label] +def lookup_expunged_node(builder, node): + return next( + expunged for expunged in builder.cache.graph.nodes() + if expunged.node_id == node.node_id + ) + def test_get_file_read_groups(graph, index): f_ids = {n.node_id for n in graph.nodes(md.SubmittedAlignedReads).all()} assert not [d for d in index.files if d['file_id'] in f_ids] @@ -352,24 +351,25 @@ def test_get_file_read_groups(graph, index): (md.AlignmentWorkflow, 2), (md.SomaticMutationCallingWorkflow, 2), ]) -def test_get_analysis_read_groups(graph, cached_builder, cls, count): +def test_get_analysis_read_groups(graph, builder, cls, count): for workflow in graph.nodes(cls).all(): - read_groups = list(cached_builder.get_analysis_read_groups(workflow)) + workflow = lookup_expunged_node(builder, workflow) + read_groups = list(builder.get_analysis_read_groups(workflow)) assert len(read_groups) == count for read_group in read_groups: assert read_group.label == 'read_group' - @pytest.mark.parametrize('cls,count', [ (md.AlignedReads, 1), (md.CopyNumberSegment, 1), (md.RunMetadata, 1), (md.ExperimentMetadata, 1), ]) -def test_get_file_associated_entities(graph, cached_builder, cls, count): +def test_get_file_associated_entities(graph, builder, cls, count): for node in graph.nodes(cls).all(): - if cached_builder.is_file_indexed(node): - entities = list(cached_builder.get_file_associated_entities(node)) + if builder.cache.is_file_indexed(node): + node = lookup_expunged_node(builder, node) + entities = list(builder.get_file_associated_entities(node)) assert len(entities) == count @@ -377,11 +377,12 @@ def test_get_file_associated_entities(graph, cached_builder, cls, count): (md.BiospecimenSupplement, 0), (md.ClinicalSupplement, 0), ], scope='module') -def test_add_related_files(graph, cached_builder, cls, count): +def test_add_related_files(graph, builder, cls, count): for node in graph.nodes(cls).all(): - if cached_builder.is_file_indexed(node): + if builder.cache.is_file_indexed(node): + node = lookup_expunged_node(builder, node) doc = {} - cached_builder.add_related_files(node, doc) + builder.add_related_files(node, doc) assert len(doc.get('metadata_files', [])) == count @@ -391,11 +392,12 @@ def test_add_related_files(graph, cached_builder, cls, count): (md.AlignedReads, False), (md.CopyNumberSegment, False), ], scope='module') -def test_add_archive(graph, cached_builder, cls, has_archive): +def test_add_archive(graph, builder, cls, has_archive): for node in graph.nodes(cls).all(): - if cached_builder.is_file_indexed(node): + if builder.cache.is_file_indexed(node): + node = lookup_expunged_node(builder, node) doc = {} - cached_builder.add_archives(node, doc) + builder.add_archives(node, doc) assert ('archive' in doc) == has_archive diff --git a/tests/test_suite_data.gv.pdf b/tests/test_suite_data.gv.pdf index 7ff20f2196ec3c9888ca438ca5ea4adaff4aaa4d..b3d1190f59a563137734e32318a29228f819ca75 100644 GIT binary patch delta 18124 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 Z?64GPkmLVD*kP?OpdAQ_bocWB{Tr9E`S$<- delta 18123 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

McG>mR7V|L0 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

0$$ATe}S+@^K zS~0tC$ZE3)1y6sNPO^W5)t@N1#t&*Mllk#FB$p_&F^&9)dIN_u>*>{zB=hUuzzBe;}S5C*JvaP!f2?Z2?i)9!hBo zC1jR411cK`HD---;FNEonx?dKPxxjb2Xu%P+@QI$e_Ol45ER~Z_}CAVOLL$XGoezBN~J zHlc26=g;k60+JCquu(?kYg{u?cKl?D;ZqUa-os+659k}KaSKoNZ&ecJb*zJbDrdE} zZQ62HEmejJh{+=lwv9T%GRErp{1wuAk-b&?V9K9y*q3%kojR;s<^7QJof5aC=1Y;M z$cm8CLBV|8Y5dg8?J%-?(p<{#(zoi4NnA~sN4?s9-N?z54)*HjXu227Hord+a$=xfZ?AXy zNbglDL9X&~i=lmT`-KNs6TC(CrA&im<3|9j?{3c{;C2tLc>u!H8TObpFu;t~=Qoac zY+9&EY}DWtahlB24*g-R|A|U{;~d@eyc&2$snTG$(qie<_MSZ3)T~y=INAruO=TIQ znrY?Y68jw=_=3Cl+3V41W$WgR=+pc1z0SqUpZA5_UV66Ny(2;ybDaxAo19~}(_Zg2 zoU`-KY_Pe?^r>I7;)x?mxnCEOYgCgTeVx#)(WAE8&HPw58Dr3i>#5x%eu6X4c#;fa z9!}G{qY?VL{6>_8<{*BfQf>g~wjVrpCBN$KFKj}Rx}|{oed6OpS#%%$ZdrNDx%peo zi;H~n(Wi4e3Mc$~i0tDcV?`93BD($^0tKKjSoV^rN)g$Z+n}WAhs8k={{%{hg8nT4 z20$XeH8kp5!(zTM3=+qdHsVjxaF|E{g~Q;&(I{F3HXIvngGM4EX;>5u003JW9(4Tw SP1s>g5LFwHnVE}^E9fr-E)fj? From 47e34d6272d24948fcdbb9768063e18c3e469a78 Mon Sep 17 00:00:00 2001 From: Joshua Miller Date: Tue, 18 Oct 2016 08:12:52 -0500 Subject: [PATCH 08/37] active: all but annotations passing --- esbuild/graph/common/builder.py | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/esbuild/graph/common/builder.py b/esbuild/graph/common/builder.py index 1b57fedb..e50b82cf 100644 --- a/esbuild/graph/common/builder.py +++ b/esbuild/graph/common/builder.py @@ -1261,25 +1261,6 @@ def denormalize_all(self): projects = self.denormalize_projects() return cases, files, annotations, projects - def denormalize_cases_sample(self, k=10): - """Return an entire index worth of case, file, annotation - documents - - """ - cases = random.sample(self.cache.cases, k) - cases, files, annotations = self.denormalize_cases(cases) - return cases, files, annotations - - def denormalize_sample(self, k=10): - """Return an entire index worth of case, file, annotation, and - project documents - - """ - cases, files, annotations = self.denormalize_sample_cases(k) - projs = random.sample(self.projects, 1) - projects = self.denormalize_projects(projs) - return cases, files, annotations, projects - ################################################################### # Validation functions ################################################################### From a12d8694f1933fd8c2a013907028157a5126c288 Mon Sep 17 00:00:00 2001 From: Joshua Miller Date: Tue, 18 Oct 2016 08:23:58 -0500 Subject: [PATCH 09/37] with lru_cached annotation docs --- esbuild/graph/common/builder.py | 18 ++++++++++++++++-- esbuild/graph/common/cache.py | 27 --------------------------- tests/test_suite_data.gv.pdf | Bin 46205 -> 46199 bytes 3 files changed, 16 insertions(+), 29 deletions(-) diff --git a/esbuild/graph/common/builder.py b/esbuild/graph/common/builder.py index e50b82cf..bfd4c706 100644 --- a/esbuild/graph/common/builder.py +++ b/esbuild/graph/common/builder.py @@ -11,6 +11,7 @@ from cdisutils.log import get_logger from collections import defaultdict from copy import copy, deepcopy +from functools32 import lru_cache from gdcdatamodel import models as md from psqlgraph import Node, Edge from sqlalchemy.orm import joinedload @@ -950,6 +951,20 @@ def add_cases(self, node, ptree, doc): return relevant + @lru_cache(maxsize=int(2**20)) + def get_node_annotation_docs(self, node): + """Returns the annotation docs for all annotations relevant to this + node + + """ + + annotations = self.cache.neighbors_labeled(node, 'annotation') + + return [ + self.denormalize_annotation(annotation) + for annotation in annotations + ] + def add_annotations(self, node, relevant, doc): """Given a file node, aggregate all of the annotations from a pruned case tree and insert them at the root level of the file @@ -960,8 +975,7 @@ def add_annotations(self, node, relevant, doc): annotations = doc.pop('annotations', []) for relevant_node in relevant: - ann_docs = self.cache.annotation_entities.get(relevant_node, {}) - annotations.extend(ann_docs.values()) + annotations.extend(self.get_node_annotation_docs(relevant_node)) if annotations: doc['annotations'] = annotations diff --git a/esbuild/graph/common/cache.py b/esbuild/graph/common/cache.py index 5b4fef6f..3cb47e27 100644 --- a/esbuild/graph/common/cache.py +++ b/esbuild/graph/common/cache.py @@ -99,8 +99,6 @@ def __init__(self, psqlgraph_driver, caching_options): self.projects = None self.relevant_nodes = None self.annotations = None - # FIXME - self.annotation_entities = {} self.entity_cases = None # Different from ``self.data_categories`` in that it's a # replacement for a hardcoded dict of data_type, data_subtype @@ -330,8 +328,6 @@ def _cache_all(self): self._cache_entity_cases() self._cache_cases() self._cache_projects() - # FIXME - # self._cache_annotations() def _cache_projects(self): """Save a list of all Project nodes""" @@ -409,29 +405,6 @@ def _cache_relevant_nodes(self): pbar.finish() - # def _cache_annotations(self): - # if not self.annotations: - # # cache what nodes are annotations - # self.annotations = list(self.nodes_labeled('annotation')) - # if self.annotation_entities: - # # we've already cached the related entities - # return - # if not self.annotations: - # # there aren't any entities to relate - # self.annotation_entities = {} - # logger.warn('No annotations found in the cached database!') - # return - # pbar = util.get_pbar('Caching annotations: ', len(self.annotations)) - # self.annotation_entities = {} - # for a in self.annotations: - # for n in self.graph.neighbors(a): - # if n not in self.annotation_entities: - # self.annotation_entities[n] = {} - # a_doc = self.denormalize_annotation(a) - # self.annotation_entities[n][a.node_id] = a_doc - # pbar.update(pbar.currval+1) - # pbar.finish() - def _cache_popular_neighbor(self, node, neighbors, labels): if node not in self.popular_nodes: self.popular_nodes[node] = {} diff --git a/tests/test_suite_data.gv.pdf b/tests/test_suite_data.gv.pdf index b3d1190f59a563137734e32318a29228f819ca75..fc328cf9cd18bd5afd62a72c925423f70cfe6ddb 100644 GIT binary patch delta 17836 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 delta 17867 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 Date: Tue, 18 Oct 2016 10:56:49 -0500 Subject: [PATCH 10/37] test_graph_legacy_builder passing --- esbuild/gdc_elasticsearch.py | 1 + esbuild/graph/common/builder.py | 9 +++++---- esbuild/graph/common/cache.py | 15 +++++++++----- esbuild/graph/legacy/builder.py | 5 +++-- tests/test_graph_legacy_builder.py | 31 ++++++++++++++++++++--------- tests/test_suite_data.gv.pdf | Bin 46199 -> 46195 bytes 6 files changed, 41 insertions(+), 20 deletions(-) diff --git a/esbuild/gdc_elasticsearch.py b/esbuild/gdc_elasticsearch.py index 90a68ceb..ae6225e2 100644 --- a/esbuild/gdc_elasticsearch.py +++ b/esbuild/gdc_elasticsearch.py @@ -44,6 +44,7 @@ def shouldnt_delete(node): delete them. """ + if isinstance(node, File) and node.derived_files: return True else: diff --git a/esbuild/graph/common/builder.py b/esbuild/graph/common/builder.py index bfd4c706..ce129836 100644 --- a/esbuild/graph/common/builder.py +++ b/esbuild/graph/common/builder.py @@ -775,7 +775,7 @@ def get_file_index_files(self, node): """Given a file, return any neighboring index files""" return [ n for n in list(self.cache.neighbors_labeled(node, 'file')) - if self.cache[node][n].get("label") == "related_to" + if self.cache.get_edge(node, n).get("label") == "related_to" and self.is_index_file(n) ] @@ -818,7 +818,7 @@ def add_related_files(self, node, doc): # Get related_files related_files = [ n for n in list(self.cache.neighbors_labeled(node, 'file')) - if self.cache[node][n].get("label") == "related_to" + if self.cache.get_edge(node, n).get("label") == "related_to" and not self.is_index_file(n) ] @@ -859,7 +859,8 @@ def add_related_files(self, node, doc): # here). For now, we don't do this for non-legacy files. if node.label == 'file': for archive in set(self.cache.neighbors_labeled(node, 'archive')): - if self.cache[node][archive].get('label') != 'member_of': + edge = self.cache.get_edge(node, archive) + if edge.get('label') != 'member_of': name = '{}.{}.0.tar.gz'.format( archive['submitter_id'], archive['revision']) rf_docs.append({ @@ -891,7 +892,7 @@ def add_archives(self, node, doc): is_skipped_legacy_edge = ( node.label == 'file' and - self.cache[node][archive].get('label') != 'member_of' + self.cache.get_edge(node, archive).get('label') != 'member_of' ) if not is_skipped_legacy_edge: diff --git a/esbuild/graph/common/cache.py b/esbuild/graph/common/cache.py index 3cb47e27..b3e1015d 100644 --- a/esbuild/graph/common/cache.py +++ b/esbuild/graph/common/cache.py @@ -133,6 +133,11 @@ def error(*args, **kwargs): util.log_error(logger, *args, **kwargs) + def get_edge(self, src, dst): + """Returns any information stored about the edge between two nodes""" + + return self.graph[src][dst] + def get_suppressed_children(self, redacted): """Get the children of a redacted node""" @@ -540,10 +545,10 @@ def is_harmonized_file(node): def is_old_supplement_file(self, node): return ( - node.label == 'file' and - any( - p.match(node._props.get('file_name', '')) - for p in self.caching_options.supplement_regexes + node.label == 'file' + and any( + pattern.match(node._props.get('file_name', '')) + for pattern in self.caching_options.supplement_regexes ) ) @@ -671,6 +676,6 @@ def walk_paths(self, node, paths, whole=False): return { n for n in itertools.chain(*[ self.walk_path(node, path, whole=whole) - for path in paths + for path in paths if path ]) } diff --git a/esbuild/graph/legacy/builder.py b/esbuild/graph/legacy/builder.py index 0fcdd6ad..61320087 100644 --- a/esbuild/graph/legacy/builder.py +++ b/esbuild/graph/legacy/builder.py @@ -86,7 +86,7 @@ def denormalize_archive_files(self, visited_file_ids=None): """ - archives = self.nodes_labeled('archive') + archives = self.cache.nodes_labeled('archive') file_docs = [] if visited_file_ids is None: @@ -95,7 +95,8 @@ def denormalize_archive_files(self, visited_file_ids=None): for archive in archives: file_docs.append(self.get_archive_as_file_doc(archive)) - for file_ in self.neighbors_labeled(archive, self.file_labels): + files = self.cache.neighbors_labeled(archive, self.file_labels) + for file_ in files: # skip any files visited in or before this function if file_.node_id in visited_file_ids: continue diff --git a/tests/test_graph_legacy_builder.py b/tests/test_graph_legacy_builder.py index 8c27025e..ab7f5169 100644 --- a/tests/test_graph_legacy_builder.py +++ b/tests/test_graph_legacy_builder.py @@ -10,6 +10,7 @@ from conftest import Index, _graph from data import fuzzed from esbuild.graph.legacy.builder import LegacyGraphIndexBuilder +from esbuild.graph.common.cache import CachedGraph from gdcdatamodel import models as md from jsonpath_rw import parse @@ -20,11 +21,16 @@ ) +def new_cache(graph=_graph): + options = LegacyGraphIndexBuilder.get_caching_options() + cache = CachedGraph(graph, options) + cache.cache_database() + return cache + + def build_index(graph): - builder = LegacyGraphIndexBuilder(graph) - builder.cache_database() - index = builder.denormalize_all() - return Index._make(index) + builder = LegacyGraphIndexBuilder(new_cache(graph)) + return Index._make(builder.denormalize_all()) # ====================================================================== @@ -33,7 +39,8 @@ def build_index(graph): @pytest.fixture() def builder(): - return LegacyGraphIndexBuilder(_graph) + return LegacyGraphIndexBuilder(new_cache()) + @pytest.fixture(scope="module") @@ -103,10 +110,14 @@ def test_path_value_in(index, doc_type, path, expected, count): assert actual.value in expected -def test_omitted_projects(graph): - builder = LegacyGraphIndexBuilder(graph) - builder.omitted_projects.add(('TCGA', 'BRCA')) - builder.cache_database() +def test_omitted_projects(graph, monkeypatch): + caching_options = LegacyGraphIndexBuilder.get_caching_options() + monkeypatch.setattr(caching_options, 'omitted_projects', + caching_options.omitted_projects.union({('TCGA', 'BRCA')})) + + cache = CachedGraph(graph, caching_options) + cache.cache_database() + builder = LegacyGraphIndexBuilder(cache) index = Index._make(builder.denormalize_all()) assert index.cases == [] @@ -146,7 +157,9 @@ def test_non_case_suppression(graph): redacted2.aliquots = [aliquot] s.add(redacted1) s.add(redacted2) + index = build_index(graph) + case_doc = [c for c in index.cases if c["case_id"] == case.node_id][0] sample_doc = [s for s in case_doc["samples"] if s["sample_id"] == sample.node_id][0] assert portion.node_id not in [ diff --git a/tests/test_suite_data.gv.pdf b/tests/test_suite_data.gv.pdf index fc328cf9cd18bd5afd62a72c925423f70cfe6ddb..1af64ff745c185a545af23ac7dc25ff0b98ff9d0 100644 GIT binary patch delta 18104 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 U(ZL}=8#D%E4TQnYx)Fi@1*vNFR{#J2 From abb23ed68620aaa0961256d1d956eae97ff96b16 Mon Sep 17 00:00:00 2001 From: Joshua Miller Date: Tue, 18 Oct 2016 11:06:58 -0500 Subject: [PATCH 11/37] test_graph_legacy_builder passing --- esbuild/gdc_elasticsearch.py | 11 +++++++---- tests/test_suite_data.gv.pdf | Bin 46195 -> 46203 bytes 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/esbuild/gdc_elasticsearch.py b/esbuild/gdc_elasticsearch.py index ae6225e2..10188d7a 100644 --- a/esbuild/gdc_elasticsearch.py +++ b/esbuild/gdc_elasticsearch.py @@ -19,6 +19,7 @@ from gdcdatamodel.models import File from progressbar import ProgressBar, Percentage, Bar, ETA from psqlgraph import PsqlGraphDriver +from esbuild.graph.common.cache import CachedGraph # TODO this could probably be bumped now that the number of bulk # threads in the config is higher, c.f. @@ -56,8 +57,7 @@ class GDCElasticsearch(object): """ """ - def __init__(self, converter_class, es=None, - index_base="gdc_from_graph"): + def __init__(self, converter_class, es=None, index_base="gdc_from_graph"): """Walks the graph to produce elasticsearch json documents. :param es: An instance of Elasticsearch class @@ -83,7 +83,10 @@ def __init__(self, converter_class, es=None, os.environ["PG_NAME"], ) - self.converter = converter_class(self.graph) + cache = CachedGraph(self.graph, converter_class.get_caching_options()) + converter = converter_class(cache) + + self.converter = converter def go(self, roll_alias=True): self.log.info("Caching database") @@ -91,7 +94,7 @@ def go(self, roll_alias=True): # that the cached database and which nodes get deleted is # consistent with self.graph.session_scope() as session: - self.converter.cache_database() + self.converter.cache.cache_database() self.log.info("Querying for old nodes to delete") to_delete = self.graph.nodes().sysan({"to_delete": True}).all() to_delete = [n for n in to_delete if not shouldnt_delete(n)] diff --git a/tests/test_suite_data.gv.pdf b/tests/test_suite_data.gv.pdf index 1af64ff745c185a545af23ac7dc25ff0b98ff9d0..4a0178e662ef4d84a7d436fd173efdf054499073 100644 GIT binary patch delta 18148 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 w%94b(!~zIp6d8de;Xo(;M1& delta 18130 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 a#wQT2CH!`cL Date: Tue, 18 Oct 2016 11:09:04 -0500 Subject: [PATCH 12/37] wip to fix gdc_elasticsearch regressions --- esbuild/gdc_elasticsearch.py | 3 ++- tests/test_suite_data.gv.pdf | Bin 46203 -> 46208 bytes 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/esbuild/gdc_elasticsearch.py b/esbuild/gdc_elasticsearch.py index 10188d7a..8f9b84cc 100644 --- a/esbuild/gdc_elasticsearch.py +++ b/esbuild/gdc_elasticsearch.py @@ -83,7 +83,8 @@ def __init__(self, converter_class, es=None, index_base="gdc_from_graph"): os.environ["PG_NAME"], ) - cache = CachedGraph(self.graph, converter_class.get_caching_options()) + caching_options = converter_class.get_caching_options() + cache = CachedGraph(self.graph, caching_options) converter = converter_class(cache) self.converter = converter diff --git a/tests/test_suite_data.gv.pdf b/tests/test_suite_data.gv.pdf index 4a0178e662ef4d84a7d436fd173efdf054499073..ace0d157164fbd57cf5b8695dfda1ca1a97d1c7e 100644 GIT binary patch delta 18148 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 aAZjWpB{e-Ih71DGHa2LGsi~`<8|dF$m=OE` From 4c994b20b4e25723e20201d014d5ce08fe5cc7a1 Mon Sep 17 00:00:00 2001 From: Joshua Miller Date: Tue, 18 Oct 2016 14:03:38 -0500 Subject: [PATCH 13/37] wip: nodes are being copied across the queue and aren't in the graph --- esbuild/graph/common/builder.py | 135 ++++++++++++++++++++++++++--- tests/test_graph_active_builder.py | 11 ++- tests/test_suite_data.gv | 18 ++-- tests/test_suite_data.gv.pdf | Bin 46208 -> 46227 bytes 4 files changed, 140 insertions(+), 24 deletions(-) diff --git a/esbuild/graph/common/builder.py b/esbuild/graph/common/builder.py index ce129836..158a1991 100644 --- a/esbuild/graph/common/builder.py +++ b/esbuild/graph/common/builder.py @@ -13,6 +13,7 @@ from copy import copy, deepcopy from functools32 import lru_cache from gdcdatamodel import models as md +from multiprocessing import cpu_count, Queue, Process from psqlgraph import Node, Edge from sqlalchemy.orm import joinedload @@ -26,6 +27,7 @@ from esbuild.graph.common.cache import ( CachingOptions, + CachedGraph, ) from .mappings import ( @@ -37,6 +39,127 @@ log.setLevel(level=logging.INFO) +def upsert_file_into_dict(files, file_doc): + """Merge this file document into all other relevant file documents (or + just add it if none exist) + + TODO: make this more descriptive + + """ + + did = file_doc['file_id'] + + if did not in files: + files[did] = file_doc + return + + for case in file_doc['cases']: + case_id = case['case_id'] + + existing_ids = { + case['case_id'] + for case in files[did]['cases'] + } + + if case_id not in existing_ids: + files[did]['cases'] += file_doc['cases'] + + +def build_index_serial(builder_class, graph): + """TODO: docstring + + """ + + caching_options = builder_class.get_caching_options() + cache = CachedGraph(graph, caching_options) + builder = builder_class(cache) + + return builder.denormalize_all() + + +def build_worker(builder, case_in_q, result_q): + """TODO: docstring + + """ + + while True: + case = case_in_q.get() + if case is None: + return log.info('No more work for builder %s', builder) + result_q.put(builder.denormalize_case(case)) + + +def start_worker_pool(builders, cases): + """Setup a process pool and schedule work to the case_in_q""" + + case_in_q, result_q = Queue(), Queue() + + pool = [ + Process( + target=build_worker, + args=(builder, case_in_q, result_q) + ) for builder in builders + ] + + # Schedule work + for case in cases: + case_in_q.put(case) + + # Put an end of work marker for all workers + for _ in range(len(builders)): + case_in_q.put(None) + + # Start all of the processes + for process in pool: + process.start() + + return case_in_q, result_q, pool + + +def build_index(builder_class, graph, cases=None, threads=cpu_count()): + """TODO: docstring + + """ + + if threads <= 1: + return build_index_serial(builder_class, graph) + + caching_options = builder_class.get_caching_options() + cache = CachedGraph(graph, caching_options) + cache.cache_database() + + case_docs, ann_docs, file_docs = [], {}, {} + + # Map work to worker processes + cases = cases or cache.cases + builders = [builder_class(cache) for _ in range(threads)] + _, result_q, pool = start_worker_pool(builders, cases) + + pbar = util.get_pbar('Denormalizing cases ', len(cases)) + + # Collect results + while len(case_docs) < len(cases): + case_doc, files, annotations = result_q.get() + case_docs.append(case_doc) + + # Collect annotation docs + for annotation in annotations: + if annotation['annotation_id'] not in ann_docs: + ann_docs[annotation['annotation_id']] = annotation + + # Collect file docs + for file_ in files: + upsert_file_into_dict(file_docs, file_) + + pbar.update(pbar.currval+1) + pbar.finish() + + for process in pool: + process.join() + + return case_docs, file_docs.values(), ann_docs.values() + + class GraphIndexBuilder(object): """This class handles all of the JSON production for the GDC @@ -1032,18 +1155,6 @@ def add_file_associated_entities(self, node, doc, case_id): if docs: doc['associated_entities'] = docs - def upsert_file_into_dict(self, files, file_doc): - did = file_doc['file_id'] - if did not in files: - files[did] = file_doc - else: - for case in file_doc['cases']: - case_id = case['case_id'] - existing_ids = { - p['case_id'] for p in files[did]['cases']} - if case_id not in existing_ids: - files[did]['cases'] += file_doc['cases'] - ################################################################### # Project summaries ################################################################### diff --git a/tests/test_graph_active_builder.py b/tests/test_graph_active_builder.py index 62db058b..3f5e98a0 100644 --- a/tests/test_graph_active_builder.py +++ b/tests/test_graph_active_builder.py @@ -29,6 +29,11 @@ CachedGraph, ) +from esbuild.graph.common.builder import ( + build_index, +) + + # Define the number of files that should be loaded as documents N_FILES = 9 @@ -45,9 +50,9 @@ def cached_graph(): @pytest.fixture(scope='module') -def index(cached_graph): - builder = ActiveGraphIndexBuilder(cached_graph) - return Index._make(builder.denormalize_all()) +def index(): + doc_types = build_index(ActiveGraphIndexBuilder, _graph) + return Index._make(doc_types) @pytest.fixture(scope='module') diff --git a/tests/test_suite_data.gv b/tests/test_suite_data.gv index 83c26ed5..e3adf706 100644 --- a/tests/test_suite_data.gv +++ b/tests/test_suite_data.gv @@ -2,7 +2,6 @@ digraph { graph [rankdir=RL] "5fa9998b-deff-493e-8a8e-dc2422192a48" [label=] "5fa9998b-deff-493e-8a8e-dc2422192a48" -> "eda6d2d5-4199-4f76-a45b-1d0401b4e54c" - "40407260-e805-4c2e-b2a7-13862bc5e494" -> "5fa9998b-deff-493e-8a8e-dc2422192a48" "008ba655-a0a3-42c4-8c72-f1341365ef02" -> "5fa9998b-deff-493e-8a8e-dc2422192a48" "aliquot-without-downstream" -> "5fa9998b-deff-493e-8a8e-dc2422192a48" "0ffb3f3d-f20e-43d1-9867-7dc75ac24f3b" -> "5fa9998b-deff-493e-8a8e-dc2422192a48" @@ -11,6 +10,7 @@ digraph { "05c45162-6c94-4a15-accc-b6239451064c" -> "5fa9998b-deff-493e-8a8e-dc2422192a48" "7b017050-97d4-45bb-bf83-c89dab812e44" -> "5fa9998b-deff-493e-8a8e-dc2422192a48" "6d066a72-f59f-45a8-ab90-216000b36da4" -> "5fa9998b-deff-493e-8a8e-dc2422192a48" + "40407260-e805-4c2e-b2a7-13862bc5e494" -> "5fa9998b-deff-493e-8a8e-dc2422192a48" "b3601406-3676-4f76-9aa0-ed68ed6c3a05" [label=] "b3601406-3676-4f76-9aa0-ed68ed6c3a05" -> "64f66bc3-1cee-41d7-ae86-cb443e84f30e" "973bd442-04a0-4189-8f02-c8c7e041afe9" -> "b3601406-3676-4f76-9aa0-ed68ed6c3a05" @@ -22,14 +22,14 @@ digraph { "84df0f82-69c4-4cd3-a4bd-f40d2d6ef916" [label=] "84df0f82-69c4-4cd3-a4bd-f40d2d6ef916" -> "c1e5beaa-6103-409d-bdd4-a86c0f210014" "84df0f82-69c4-4cd3-a4bd-f40d2d6ef916" -> "c8611490-4cbd-5651-8de2-64484a515eec" + "64f66bc3-1cee-41d7-ae86-cb443e84f30e" -> "84df0f82-69c4-4cd3-a4bd-f40d2d6ef916" + "cnv-file-1" -> "84df0f82-69c4-4cd3-a4bd-f40d2d6ef916" "live-file" -> "84df0f82-69c4-4cd3-a4bd-f40d2d6ef916" "legacy-file-with-empty-acl" -> "84df0f82-69c4-4cd3-a4bd-f40d2d6ef916" "harmonized-file" -> "84df0f82-69c4-4cd3-a4bd-f40d2d6ef916" "non-live-file" -> "84df0f82-69c4-4cd3-a4bd-f40d2d6ef916" "to-delete-file" -> "84df0f82-69c4-4cd3-a4bd-f40d2d6ef916" "related-file" -> "84df0f82-69c4-4cd3-a4bd-f40d2d6ef916" - "cnv-file-1" -> "84df0f82-69c4-4cd3-a4bd-f40d2d6ef916" - "64f66bc3-1cee-41d7-ae86-cb443e84f30e" -> "84df0f82-69c4-4cd3-a4bd-f40d2d6ef916" "d7cb38ff-0ca2-5496-896b-92c5a76b6109" -> "84df0f82-69c4-4cd3-a4bd-f40d2d6ef916" "rescinded-annotation" -> "84df0f82-69c4-4cd3-a4bd-f40d2d6ef916" biospecimen_supplement_1 [label=] @@ -50,10 +50,10 @@ digraph { "live-file" -> data_subtype_aligned_reads "live-file" -> "index-file" "live-file" -> "related-file" + "run-metadata-1" -> "live-file" + "analysis-metadata-1" -> "live-file" "experiment-metadata-1" -> "live-file" "harmonized-file" -> "live-file" - "analysis-metadata-1" -> "live-file" - "run-metadata-1" -> "live-file" "a2b74dcc-052a-42ce-836e-c2fb549beea5" [label=] "old-biospecimen-supplement-xml" [label=] "old-biospecimen-supplement-xml" -> "eda6d2d5-4199-4f76-a45b-1d0401b4e54c" @@ -119,6 +119,7 @@ digraph { "c1fd82a9-f75f-4297-b2c2-ec91c40a57f4" -> "956ca84c-1124-53ff-824f-fa0c84425425" "cnv-file-1" [label=] "cnv-workflow-1" -> "cnv-file-1" + "non-live-file" [label=] "snv-file" [label=] "snv-file" -> "eda6d2d5-4199-4f76-a45b-1d0401b4e54c" "bd4d1c78-c448-4bbf-8348-a77f3786c648" [label=] @@ -131,15 +132,15 @@ digraph { "64f66bc3-1cee-41d7-ae86-cb443e84f30e" [label=] "read-group-qc-1" -> "64f66bc3-1cee-41d7-ae86-cb443e84f30e" "40407260-e805-4c2e-b2a7-13862bc5e494" [label=] + "3013e9be-aa3e-4986-990c-559982f00e36" -> "40407260-e805-4c2e-b2a7-13862bc5e494" "3febc6c8-85ae-4d38-ba55-c959959846db" -> "40407260-e805-4c2e-b2a7-13862bc5e494" "5f5b9bb2-3278-424f-9cf2-e26f0c3b0fd5" -> "40407260-e805-4c2e-b2a7-13862bc5e494" - "3013e9be-aa3e-4986-990c-559982f00e36" -> "40407260-e805-4c2e-b2a7-13862bc5e494" "5f5b9bb2-3278-424f-9cf2-e26f0c3b0fd5" [label=] "6d066a72-f59f-45a8-ab90-216000b36da4" -> "5f5b9bb2-3278-424f-9cf2-e26f0c3b0fd5" "c1e5beaa-6103-409d-bdd4-a86c0f210014" [label=] "c1e5beaa-6103-409d-bdd4-a86c0f210014" -> "eda6d2d5-4199-4f76-a45b-1d0401b4e54c" - "5b2a99b7-e1a8-4739-acaf-d5f75cc47021" -> "c1e5beaa-6103-409d-bdd4-a86c0f210014" "0395a62f-3f37-4068-bab6-4c1d29cef2d5" -> "c1e5beaa-6103-409d-bdd4-a86c0f210014" + "5b2a99b7-e1a8-4739-acaf-d5f75cc47021" -> "c1e5beaa-6103-409d-bdd4-a86c0f210014" clinical_supplement_1 [label=] clinical_supplement_1 -> "eda6d2d5-4199-4f76-a45b-1d0401b4e54c" clinical_supplement_1 -> archive_1 @@ -157,7 +158,7 @@ digraph { "5b2a99b7-e1a8-4739-acaf-d5f75cc47021" [label=] "0395a62f-3f37-4068-bab6-4c1d29cef2d5" [label=] "analysis-metadata-1" [label=] - "non-live-file" [label=] + "index-file-2" [label=] "aggregated-somatic-mutation-1" [label=] "experiment-metadata-1" [label=] archive_1 [label=] @@ -189,7 +190,6 @@ digraph { "3febc6c8-85ae-4d38-ba55-c959959846db" [label=] "7b017050-97d4-45bb-bf83-c89dab812e44" -> "3febc6c8-85ae-4d38-ba55-c959959846db" "008ba655-a0a3-42c4-8c72-f1341365ef02" -> "3febc6c8-85ae-4d38-ba55-c959959846db" - "index-file-2" [label=] "008ba655-a0a3-42c4-8c72-f1341365ef02" [label=] "7ef3885b-37ce-5e16-8ba3-9d75b6690008" [label=] "7b017050-97d4-45bb-bf83-c89dab812e44" -> "7ef3885b-37ce-5e16-8ba3-9d75b6690008" diff --git a/tests/test_suite_data.gv.pdf b/tests/test_suite_data.gv.pdf index ace0d157164fbd57cf5b8695dfda1ca1a97d1c7e..ad5b6a08215097b06bb50f573e9cf653ecefd849 100644 GIT binary patch delta 41741 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 E2Z@nlZ~y=R From 2aa99926cccd2a2a7c021fd2c01f4fff5ac31f16 Mon Sep 17 00:00:00 2001 From: Joshua Miller Date: Tue, 18 Oct 2016 14:13:24 -0500 Subject: [PATCH 14/37] wip: nodes are being copied across the queue and aren't in the graph --- esbuild/graph/common/cache.py | 37 +++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/esbuild/graph/common/cache.py b/esbuild/graph/common/cache.py index b3e1015d..ac97ce40 100644 --- a/esbuild/graph/common/cache.py +++ b/esbuild/graph/common/cache.py @@ -17,6 +17,7 @@ from gdcdatamodel import models as md from psqlgraph import Edge, Node from sqlalchemy.orm import joinedload +from types import StringTypes from esbuild.graph.common import ( util, @@ -25,8 +26,25 @@ logger = get_logger(__name__) logger.setLevel(logging.INFO) +def to_node_id(node_or_node_id): + """Returns the node_id of a node if provided a Node, elif it's a + string, assume it's a node_id and return that + + """ + + if hasattr(node_or_node_id, 'node_id'): + return node_or_node_id.node_id + + elif isinstance(node_or_node_id, StringTypes) + return node_or_node_id.node_id + + else: + raise TypeError("Not sure how to convert {} to node_id" + .format(node_or_node_id)) + class CachingOptions(object): + """An object to hold the options required to hold the required options to cache information to a SharedGraph object @@ -92,6 +110,7 @@ def __init__(self, psqlgraph_driver, caching_options): self.caching_options = caching_options # Cached information + self.nodes = {} self.experimental_strategies = {} self.data_categories = {} self.popular_nodes = {} @@ -162,6 +181,15 @@ def get_suppressed_children(self, redacted): return to_suppress + def get_node_in_graph(self, node_or_node_id): + return self.nodes[node_or_node_id(node_or_node_id)] + + def neighbors(self, node_or_node_id): + """Get the neighbors of a given node""" + + node = self.get_node_in_graph(node_or_node_id) + + def suppressed_nodes(self): """ Find all nodes that need to be suppressed due to redactions. @@ -326,6 +354,7 @@ def _cache_all(self): """ + self._cache_node_ids() self._cache_existing_data_types() self._cache_experimental_strategies() self._cache_data_categories() @@ -334,6 +363,14 @@ def _cache_all(self): self._cache_cases() self._cache_projects() + def cache_node_ids(self): + """Create a hashtable from node_id to node in the graph""" + + self.nodes = { + node.node_id: node + for node in self.graph.nodes_iter() + } + def _cache_projects(self): """Save a list of all Project nodes""" From fc9637c353cc71d4a7c97cd7c22359f3798a533c Mon Sep 17 00:00:00 2001 From: Joshua Miller Date: Tue, 18 Oct 2016 14:28:24 -0500 Subject: [PATCH 15/37] wip: test_graph_active works in parallel? no manager yet though --- esbuild/graph/common/builder.py | 19 ++++++++++++++++--- esbuild/graph/common/cache.py | 23 +++++++++++++++-------- tests/test_suite_data.gv.pdf | Bin 46227 -> 46229 bytes 3 files changed, 31 insertions(+), 11 deletions(-) diff --git a/esbuild/graph/common/builder.py b/esbuild/graph/common/builder.py index 158a1991..b13c2f38 100644 --- a/esbuild/graph/common/builder.py +++ b/esbuild/graph/common/builder.py @@ -83,10 +83,16 @@ def build_worker(builder, case_in_q, result_q): """ while True: + case = case_in_q.get() if case is None: return log.info('No more work for builder %s', builder) - result_q.put(builder.denormalize_case(case)) + + try: + result_q.put(builder.denormalize_case(case)) + except Exception as exception: + log.exception(exception) + result_q.put(exception) def start_worker_pool(builders, cases): @@ -139,7 +145,12 @@ def build_index(builder_class, graph, cases=None, threads=cpu_count()): # Collect results while len(case_docs) < len(cases): - case_doc, files, annotations = result_q.get() + + result = result_q.get() + if isinstance(result, Exception): + raise result + + case_doc, files, annotations = result case_docs.append(case_doc) # Collect annotation docs @@ -157,7 +168,9 @@ def build_index(builder_class, graph, cases=None, threads=cpu_count()): for process in pool: process.join() - return case_docs, file_docs.values(), ann_docs.values() + projects = builders[0].denormalize_projects() + + return case_docs, file_docs.values(), ann_docs.values(), projects class GraphIndexBuilder(object): diff --git a/esbuild/graph/common/cache.py b/esbuild/graph/common/cache.py index ac97ce40..da6ef08e 100644 --- a/esbuild/graph/common/cache.py +++ b/esbuild/graph/common/cache.py @@ -26,6 +26,7 @@ logger = get_logger(__name__) logger.setLevel(logging.INFO) + def to_node_id(node_or_node_id): """Returns the node_id of a node if provided a Node, elif it's a string, assume it's a node_id and return that @@ -35,7 +36,7 @@ def to_node_id(node_or_node_id): if hasattr(node_or_node_id, 'node_id'): return node_or_node_id.node_id - elif isinstance(node_or_node_id, StringTypes) + elif isinstance(node_or_node_id, StringTypes): return node_or_node_id.node_id else: @@ -182,15 +183,15 @@ def get_suppressed_children(self, redacted): return to_suppress def get_node_in_graph(self, node_or_node_id): - return self.nodes[node_or_node_id(node_or_node_id)] - - def neighbors(self, node_or_node_id): - """Get the neighbors of a given node""" + """Given a node or a node_id, return the corresponding node that is in + the NetworkX graph - node = self.get_node_in_graph(node_or_node_id) + """ + return self.nodes[to_node_id(node_or_node_id)] def suppressed_nodes(self): + """ Find all nodes that need to be suppressed due to redactions. """ @@ -342,6 +343,11 @@ def cache_database(self): session.expunge_all() pbar.finish() + self.nodes = { + node.node_id: node + for node in self.graph.nodes_iter() + } + # Prune graph logger.info('Cached {} nodes'.format(self.graph.number_of_nodes())) self.remove_unindexed_nodes_from_graph() @@ -363,7 +369,7 @@ def _cache_all(self): self._cache_cases() self._cache_projects() - def cache_node_ids(self): + def _cache_node_ids(self): """Create a hashtable from node_id to node in the graph""" self.nodes = { @@ -548,6 +554,7 @@ def neighbors_labeled(self, node, labels, expected=None): """ labels = tuple(labels) if hasattr(labels, '__iter__') else (labels,) + node = self.get_node_in_graph(node) if node in self.popular_nodes: if labels not in self.popular_nodes[node]: @@ -687,7 +694,7 @@ def is_node_unindexed_by_property(self, node): def neighbors(self, node): """Return the neighbors of given node""" - return self.graph.neighbors(node) + return self.graph.neighbors(self.get_node_in_graph(node)) def walk_path(self, node, path, whole=False): """Given a list of strings, treat it as a path, and yield the end of diff --git a/tests/test_suite_data.gv.pdf b/tests/test_suite_data.gv.pdf index ad5b6a08215097b06bb50f573e9cf653ecefd849..c122f2c37528b18d34843d8120da502200a0c15a 100644 GIT binary patch delta 1600 zcmaixe>l?#9LH@8Tbev76j|LNt97$qsBM&R%CE~kTtwEjAAV#u)`r?QKceGG*CxsN zv3?MDl8r;MM&0?*X(}Q)Yh@Yoqhy3_r+c3J>;AaU^L{?h>v=!#_g`XU*iA^r1mS19dv5|F;(g*# zV4?YoZcZ@H{QATwI@f`EeaQ-2$8t443*z=6Ha7GzYM3+(j? z+mVWPAf|ZVPuvx(w^vHmHs+oz-zV$pOKn{&8oF1GR3CHFWTibJ}5E_(qMmJL=5q z1xgej3}iVe$4!9q>0_ar!9mI>A{4bBbfk4A+c}*+YqYHQ*R@KVfRg0=+F|;XuN_yGevmy29Bd9?KO!y6am!i-E)Vg+=7PXEM z@&;HLB*g_g1x*)?42bREVN(aS#9msvi?Gc?4ZnVm{oTG4)h`w}kWb)S^7!Ws}$-0sA;UG#_Z z&Fs8BfZaq~HBm+04vH+vdE$Sl?ewiwAz}d}tO*Njsbhz4oCa5NF6I7w5=dOSrGzosmoaq2hP~{z)dT)2?n&PdM2C^N@(#(T<7HFa~5&-ArR(X#bh`lk~SvkDD zEGHzqTs`wLLXcyrc^fBu@S+x8iOi`Cg9nAd<=TnFiq(}=v%B0@$~;%}H<*6Q`sr$I z(oC~vTZDKfAS?#pB>l^;mJ-MdO zW_V9n^RxmEC=SBq1-lonrM1vBQ>|f9Pn(&yiH!#{pnm}mP`|WD-~YN6M2Y zFBaE0%J1%7?UnX>!xf&Z|Fbxmr!qh6#4O#WVuuEFIrlk*ktf@R8mtf}?XC?*jb`@v zDbjbEp68ps^cy6j8Z(UzI=X}Mr2)(7H2AiQ=aG$+pDp zx&s)rUf}0BUX!e2IeYG|Dv2Bm*j)H?bG+(O!}$0wp}U$!^#+iWT|dC63CEL?*;LAj z&%`_y3v7&lX+|^4Ti%L++AP}4&FgNu)hJrO86T9 delta 1613 zcmaizdpOez7{?h?n}jY$DKm96lx#M$pXQb*=gDQdA~cy>xkkr*XTmD#bk0cbLyl%j zZI~jLXlkzI5}8|$jOapZ`fcn~&vX7c{c+ys{p0g|p7;CL`+T!zA&gnby`TV1N z1}|-&6Ei9ptp+zTug>{&w()c7#A4+!U}Hx}T!OZ9k0Hg?kP0n3uv}gF#NZMyA|?+m zFAIU&kA3Xfq&BU2rC~t>VQ<$PcjGm=@w3fY^=gA^#*S@4UUqszhq_8VixYQOo0InR z6JPfliQJ)g<3IjftpN=eH*Wh&xv)i@iF`5TnYCy!tkF-^=+{-B3sak` zg3T4Rm>09cmwn6HIOK}e0v33U1rD-6J_|%eY`oG+_Ne8HUE0O15i7q>f$S-;rOrx+ z&X$zG!k62B`COdn2i#>&u2CzC9eu#R8SQqdIAGey%UGnk{EGo%#_|#2tUN( zR@xg{2slz}JFX>Vb7{3?8Smm38`ERDTlnVh@^X^rJf;3t8v?nLXGzH|=n^LbMTNB! zY*M*fRXb4D2${*8%6{LmYl2fF^+-|}m`gN9DQw^E>HyRw_^c{_!q4Z$+A^K4E>X`& zDs2mh4+7$RIxY}S)tHEvZ1Q03t||wa`!W^~s>Z=V*lvOhnvNry0t{V>5b2 zv`#WmF1;$pn{~3wW7H#tPA=nR;$J z;7gmBgJ{H~q_yL|y62*6b3G3~dDks>?L1*I^Xo2oUs0Io^VrrzJ9Q~Y4?c9J|K<3; zqvktflE%rhgEG>I88TIdVS!|yHtKxt-B0NSD=Xb&#g~sr(>}I)b)-!;bD(ynz%nLk z-80pRl(FKaOes@2DjMN{b%aWa=Sa!IHLkVZzye%_`3jbK%(=r2mD!i% z>^xGh|9s$qxgs?Gv48JR)0xKS(()k+RSmK0_bv$YQX$ybN)B1;nx z&Ox-2rm!$4g!52d6={7ylSO{T_Cjxf=miiZ?ADyGU&?B&pZGw9e3Ua9^%vyz?9V-q zW?seD-#Fy8RCZVYUYG8}pm5gtz`n<)!{66Pt}C_ZSy)gfOUiC}-}4h8f*fahYup0D z-=CU(NZpq}H35hx=7j0*7IKGq67N{YnZ^f;!o9FvQF1k21sG>HXVK^d;Z;Kh*K4 z#5Eiw4%9n`B1@}<>$SfY!P*kUFRaN0Z1nIILXZ8VzwNj679d^lOm$bCNCjQF2CsQl z@skB;eCZ8WGs4gYXk48g?HgfWv+tbZ;4Kpe1kh}m?)7dy2Tlp~J0BHEA%}dUFyCM} z28To=zXJh{#xSDpUr|P5OwkMohpC9;mU5I7Nv25jw?T#?;okvghQoeM{nwe9{ou^d zgdZKwlp*0-ojzkq!T19diZ8(&YwCyb#hMWaXsj=p;)lg!$^JMiIPrf^kX}eDEBN^+ Xa%5CYB*h<&Gs6=AxW2x0FEj>X From 6c3bc40f3de1e2db6fe544314d4de0e5f6614451 Mon Sep 17 00:00:00 2001 From: Joshua Miller Date: Tue, 18 Oct 2016 15:01:17 -0500 Subject: [PATCH 16/37] wip: manager is instantiated --- esbuild/gdc_elasticsearch.py | 4 +++- esbuild/graph/common/builder.py | 18 ++++++++++++------ esbuild/graph/common/cache.py | 28 ++++++++++++++++++++++++---- tests/conftest.py | 9 +++++++++ tests/test_graph_active_builder.py | 11 +++++++---- tests/test_suite_data.gv.pdf | Bin 46229 -> 46228 bytes 6 files changed, 55 insertions(+), 15 deletions(-) diff --git a/esbuild/gdc_elasticsearch.py b/esbuild/gdc_elasticsearch.py index 8f9b84cc..73d4218b 100644 --- a/esbuild/gdc_elasticsearch.py +++ b/esbuild/gdc_elasticsearch.py @@ -76,13 +76,15 @@ def __init__(self, converter_class, es=None, index_base="gdc_from_graph"): os.environ.get("ES_PASSWORD", "")), timeout=9999) - self.graph = PsqlGraphDriver( + self.psqlgraph_args = ( os.environ["PG_HOST"], os.environ["PG_USER"], os.environ["PG_PASS"], os.environ["PG_NAME"], ) + self.graph = PsqlGraphDriver(self.psqlgraph_args) + caching_options = converter_class.get_caching_options() cache = CachedGraph(self.graph, caching_options) converter = converter_class(cache) diff --git a/esbuild/graph/common/builder.py b/esbuild/graph/common/builder.py index b13c2f38..b3a2d5d4 100644 --- a/esbuild/graph/common/builder.py +++ b/esbuild/graph/common/builder.py @@ -28,6 +28,7 @@ from esbuild.graph.common.cache import ( CachingOptions, CachedGraph, + CacheManager, ) from .mappings import ( @@ -122,22 +123,27 @@ def start_worker_pool(builders, cases): return case_in_q, result_q, pool -def build_index(builder_class, graph, cases=None, threads=cpu_count()): +def build_index(builder_class, psqlgraph_driver_args, cases=None, + threads=cpu_count()): """TODO: docstring """ - if threads <= 1: - return build_index_serial(builder_class, graph) - + # Create managed cache caching_options = builder_class.get_caching_options() - cache = CachedGraph(graph, caching_options) + + manager = CacheManager() + manager.start() + cache = manager.new_cached_graph( + caching_options=caching_options, + psqlgraph_driver_args=psqlgraph_driver_args, + ) cache.cache_database() case_docs, ann_docs, file_docs = [], {}, {} # Map work to worker processes - cases = cases or cache.cases + cases = cases or cache.get_cases() builders = [builder_class(cache) for _ in range(threads)] _, result_q, pool = start_worker_pool(builders, cases) diff --git a/esbuild/graph/common/cache.py b/esbuild/graph/common/cache.py index da6ef08e..b10816ec 100644 --- a/esbuild/graph/common/cache.py +++ b/esbuild/graph/common/cache.py @@ -12,10 +12,11 @@ import itertools import networkx as nx -from collections import namedtuple from cdisutils.log import get_logger +from collections import namedtuple from gdcdatamodel import models as md -from psqlgraph import Edge, Node +from multiprocessing.managers import BaseManager +from psqlgraph import Edge, Node, PsqlGraphDriver from sqlalchemy.orm import joinedload from types import StringTypes @@ -103,10 +104,16 @@ class CachedGraph(object): """ - def __init__(self, psqlgraph_driver, caching_options): + @classmethod + def __init__(self, caching_options, psqlgraph_driver_args=None, + psqlgraph_driver_kwargs=None, psqlgraph_driver=None): # Injected Dependencies - self.psqlgraph_driver = psqlgraph_driver + self.psqlgraph_driver = psqlgraph_driver or PsqlGraphDriver( + *(psqlgraph_driver_args or []), + **(psqlgraph_driver_kwargs or {}) + ) + self.graph = nx.Graph() self.caching_options = caching_options @@ -126,6 +133,7 @@ def __init__(self, psqlgraph_driver, caching_options): # ``self._cache_existing_data_types()`` self.existing_data_types = {} + def iter_database_edges(self): """Returns an iterable of edges to load from the database. @@ -153,6 +161,11 @@ def error(*args, **kwargs): util.log_error(logger, *args, **kwargs) + def get_cases(self): + """Proxy to get cached cases""" + + return self.cases + def get_edge(self, src, dst): """Returns any information stored about the edge between two nodes""" @@ -723,3 +736,10 @@ def walk_paths(self, node, paths, whole=False): for path in paths if path ]) } + + +class CacheManager(BaseManager): + pass + + +CacheManager.register('new_cached_graph', CachedGraph) diff --git a/tests/conftest.py b/tests/conftest.py index b956c4a8..73cdcdaa 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -39,6 +39,15 @@ _graph = PsqlGraphDriver(PG_HOST, PG_USER, PG_PASSWORD, PG_DATABASE) +@pytest.fixture(scope='session') +def psqlgraph_args(): + return ( + PG_HOST, + PG_USER, + PG_PASSWORD, + PG_DATABASE, + ) + @pytest.fixture def clear_database(): diff --git a/tests/test_graph_active_builder.py b/tests/test_graph_active_builder.py index 3f5e98a0..a1f08331 100644 --- a/tests/test_graph_active_builder.py +++ b/tests/test_graph_active_builder.py @@ -42,16 +42,19 @@ @pytest.fixture(scope='module') -def cached_graph(): +def cached_graph(psqlgraph_args): options = ActiveGraphIndexBuilder.get_caching_options() - cache = CachedGraph(_graph, options) + cache = CachedGraph( + caching_options=options, + psqlgraph_driver_args=psqlgraph_args, + ) cache.cache_database() return cache @pytest.fixture(scope='module') -def index(): - doc_types = build_index(ActiveGraphIndexBuilder, _graph) +def index(psqlgraph_args): + doc_types = build_index(ActiveGraphIndexBuilder, psqlgraph_args) return Index._make(doc_types) diff --git a/tests/test_suite_data.gv.pdf b/tests/test_suite_data.gv.pdf index c122f2c37528b18d34843d8120da502200a0c15a..b2c5f98fdf856db1a7ea61b843a695b2b3c93d70 100644 GIT binary patch delta 18162 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 z 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

afWK?;>H#zmHk)c=loX;>Hmk#)Hxs3oqr^}w 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 From 1cc54072f585a2d9b46ab3fbea2fa687d72ce342 Mon Sep 17 00:00:00 2001 From: Joshua Miller Date: Tue, 18 Oct 2016 15:06:24 -0500 Subject: [PATCH 17/37] wip: manager is instantiated --- esbuild/graph/common/cache.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/esbuild/graph/common/cache.py b/esbuild/graph/common/cache.py index b10816ec..93116d67 100644 --- a/esbuild/graph/common/cache.py +++ b/esbuild/graph/common/cache.py @@ -707,7 +707,10 @@ def is_node_unindexed_by_property(self, node): def neighbors(self, node): """Return the neighbors of given node""" - return self.graph.neighbors(self.get_node_in_graph(node)) + return [ + neighbor.to_json() for neighbor in + self.graph.neighbors(self.get_node_in_graph(node)) + ] def walk_path(self, node, path, whole=False): """Given a list of strings, treat it as a path, and yield the end of From 5a60427137b7c36e02e1daa7f9afa4bb5d1a7041 Mon Sep 17 00:00:00 2001 From: Joshua Miller Date: Tue, 18 Oct 2016 15:32:17 -0500 Subject: [PATCH 18/37] =?UTF-8?q?=F0=9F=8E=89=20=F0=9F=8E=89=20?= =?UTF-8?q?=F0=9F=8E=89=20=F0=9F=8E=89=20=20we've=20achieved=20serializabi?= =?UTF-8?q?lity=20=F0=9F=8E=89=20=F0=9F=8E=89=20=F0=9F=8E=89=20?= =?UTF-8?q?=F0=9F=8E=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- esbuild/graph/common/cache.py | 6 +++++- tests/test_suite_data.gv.pdf | Bin 46228 -> 46228 bytes 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/esbuild/graph/common/cache.py b/esbuild/graph/common/cache.py index 93116d67..7f0728bc 100644 --- a/esbuild/graph/common/cache.py +++ b/esbuild/graph/common/cache.py @@ -24,6 +24,10 @@ util, ) +from esbuild.graph.common.fake_node import ( + FakeNode, +) + logger = get_logger(__name__) logger.setLevel(logging.INFO) @@ -317,7 +321,7 @@ def cache_database(self): for edge in self.iter_database_edges(): pbar.update(pbar.currval+1) - src, dst = edge.src, edge.dst + src, dst = FakeNode(edge.src), FakeNode(edge.dst) triple = (src.label, edge.label, dst.label) needs_differentiation = ( diff --git a/tests/test_suite_data.gv.pdf b/tests/test_suite_data.gv.pdf index b2c5f98fdf856db1a7ea61b843a695b2b3c93d70..bab9386f2b842a29dc17110b0ecebcd6e6ac4715 100644 GIT binary patch delta 18041 zcmV(-K-|BS=>nAL0((Z)b-B21P|tNJ>(({Av9Ge_uNLch7IS1|fN@ zMi|a&Myrtu-Hz0VLIV7n5aK>jJ&zbTN{++dGZ)VJ(>!D83vA+*{U0^YRqEGEuRU6x ze`dS>ZcPe0)Mw8pwF;G?OaDT7etEwB?sG?!>!4^JM%Bq-6idoR^)F^(<4oN8dIIm9 ziRCsuJ`JbmlrpH4e}YmXd|K9G6vW#&yiJAw(l&)6@AzkmhVlqS-gXF&q9JHKOYtyY zd!V%kS`^wzk&U#jp%84O=FzRtz7^V=C>ClSacC9vtb(3Z(6b797&H&|rot2E!5)pK zz#e((6lE_5d#$jSQ}(j(v@GmpmAwGP@58+O1pWw5!qX2Le*@30HUyr+y?7E@hyu8J z-wjg&&)^485b5!)N_m}Z2W>HYw+8js1ohA0o6uA^e6dnu*)UcA&QyKJRDJ7I zedAR9leh`R;V>;* zPS9UJL4V~0fBl6M^x_2lLa#pT)qA}9VZ8B>@iyZ&BT_^2z&8DD+o11@{ngn(+c5sy z!F(W@st*j~8~4pjLG`VDGam`G+3>X}!C)BCCX@gG1n||UQ>oYEoKjzbbIS3{_hl1s z+1h02 z&4gnpgCo!#MtSA1g!0N=LSwaR-^?hS&K`gl9Zd{lyf0ARGECt^fz#RPfiE+|4D@`F z8Rnt-ePWn;WMAO@EL5^1@NV{kz;9Y61dhTTo}YOl@ND+tz!NFuf`>YvB2PgN;vBwP z)&}m+e{K)lm%TCY!xrW6uDo);+h;1(js$cb3fu^{S(_Qg=j{uu$&)8&11sQ;%Tv99 zMbLe>Yz$;lg}{vLlYwd3HGwIWCynn^?%0!kLK)WIWPO`2(3bTDnp=JzXzGNK>hVkh2L--c^ zV5_s$++r$rcm9WBzS23rGx?wXd_%YQ&gdI@*w;T)LmH#L{@$Uw8Nu`W4&y)KkGeV! zf8&oy)erk3{$tm4rC;pq?|1eNO`O^{j6d#LHVg-rEf|u?!H=P1NL~OZ^bVb;+y^C~ ztMf3LNh-JxRgV(nK7g|I%4s)NPRqhw;IvLsk<(6~ta4hGI-#8Qb8_0=Es3tqy$LAb z6gGplD5q>;GvpKic;(G=aB1h>EEI5-e`W~hl=seQhLjumlpE#qa7qgl{e63D@^Hf5 ze2sEA`_Y6Wg zErD(R&`pC&okN=z27`OAy@wnK4$;y13l}XV^@1fs_ee`Rhpv@6gL~&H*Zte!e|yQ{ zxl-p|bZ^(pzPmFIRzFroWzxMg+MH=cFlxo54u@7IL%ICv}oKhVqpf3i{K))I;$FWP|a1bMOneSqqa1NiudxCQnPpx4oF z(L^){9R=EY1dl^o(PUIaD{(Ul<6okB)P;V4o`EaYqg8NjH~KCT;i@M_pM$=7^avV8 zUxFO=fmH8@Mmcy+H=2!ZLfg?D zXb8QC1NbWZeMUXHbaXj758hxoTz4Cc=5_Q(^jB=c&*GOxy`u+4N8#BLYC!GE@q5wt z(QfoZG7|I>{7#^gcm|$Le@k@jsD89&^fa7r1gOcV7o87RtVCDCNbW>0pjYAdTX z7vR?b&uB%{&*}Qqu!$3w2zL{)$|4Q?etFiL1sIKjN4LPR9;*j zEMHxIYP5Isj?qU)kHFiA@HS*ld(e0o?KCtKX7ECEr2^}%1ef4__M?OFI|Og_Bzg)R zgLnHqIt4g)2H>Dp;NS#EXTtoNBaQAKY=lQ{cjOkPu))a3vHyv0iC@JGVc|t2WDae-jDACNZpU_ z1^TE3UHm=3Oc_a{81VbN9=FTsu-mK_vq>--^g69Z&2uW2 zp+QYbbxGaxgG15zLrhfa=}D7)X#sRB_*%#Op&)d1e}D6wp&+?#0UY|qnKGPt;lG_J zSI(5ror#5D36;{RV3!me`gx}m9L95|^+EfVPN_dQbW&+gQrg>;wjSD|2p0sqoJ%`{ zLwJ6$Yp8p0>DI3Ko#_-lECcj3=@cLbKtoGzJcK$HYyfe9I>;GaLvE?FYse)*8;;SD zt_6#Sf2L0B>+1A~Vt+a{ggX{V3x|-@K4eUeT~4k8wjG(?2hUEYmVsm+LO1CaON(zB zmeIobq_yDuz9D)+{}45wJj0Y6a!8#+jw?TMezkkH)phgN4h~U~?gdM>b`Qz(Zvvo` z-T7p1!OgJOOQh@&b$x%|5WXH>j=Y5O?v+tge*{}({_^0ET56Y;Ze2bfV2-Bu?Q_d+ zMS={WseSugvP;=Xrw%(eHi-a~!|Aqk8>yQ_=f+C?$8S~oe|dz|&W%TZ2X*iCb8x}r z+0uA;&7t5T|NT%}~MhpR&R&h%Fy#JNDrep zL5F3Xa5d~CQqWN)LaQnj?1s1QCi52D8r(X5@z!8>a4AeU6H#h7uw-k07KSsUZyA&` z`@|u+-*c|Hq`$ur?vo_=XQvk|f8qaY z2-lo@Z@4lKZ(E~4xc2`g2-p2@AYA{yf^gy7n|=er4e-td0^#EScMxv;8id)GkVrj@ zE`Y5bwy9v#m|^=6wr1G+VROLN23t35aoASE)(qGA+4GPDTb|s5`4G-qiyY9d9=oT~ z$N7{#a!iE&W;ma;XTkYi?iQqme|sVN7Sszh2Xz+eYN+GzF63GDu$ieM>=#G3LYskh zL{)_6A!VzDn%tur&R5euv=olJV4sX30?(_0T7u0B_pF8Iw!+p9k38$Y(IFMS687Vu z`&H~W*a6*!{4t>6s6h7fK+hVa1y7e=>Hn%QfaWD26EcH-YXyzat{ie8e0u82aQ>4ibpiJ}<1LjojY5~V%EYt;KRvgW_ES8HF> z)#`q!@6-Rwu+Mm@aK7-Ge_3M=TXdH1SiROi*simEX+Q4R==j8WsVn2U(tV*v@NDrm zct7`D;&1fd8>kPw7<^d#PAC(4P+Aji1RYZZE94HaLui=ejsp}P&#J&3A$t+Sji-@@ zWyaGq@ff*y^=D%DbZ0U-`BZ7rNNKY0WoeQyQbMhzk&1mVRVsSX!%uo0plgn%w z#@hYjw<-^sG;(Tk*OJbUQERKYSi~lC5i0aE;b+x3v!%Y^P;n}g;4nM5XpAyl@cO2o zSax@<&rJKB`>I<{f6^CVZudfQ)B0bPcbCsRRDNf>*z_p&fm=y=pL%$oaqvD?G(irk zDQpxt75vj$BWF|zCY8kw?_}-K{>13A*_C&ibe=N!NvB4>`A&`^5|md$1Bl|_mAF`a zq246Ks93@7Fq^1xlY6Ipdv=rM?r|F%r@iU^!In4hqVku6e;Zf!_{7VudMIrO(NqR3kA1o6;x=ju}ia*nRWTjs~Z=;V8U5)D4qMn|}t9JQW!!Em?+F~B2 z`29i67WXj4f9(whvd2!H6uvx(T2HpZ-8$Vx#P@OLdam9l0vk~W_8%}W}@_Rlo*Od zO+ukQPi?qFYGUp#^C^4<67l_b0FB{1Ap6+Fms-t^ z;-oK5f1bf#B$L%S1Ov0%Ojf(YCf2p!I#X>_3aPldNS<1Vr(Zg9Z2bgh+&v?VSLxV( zR(*Qnq$P%4B)S_F|fR&c+d%)OTp_z0(mSypRwTGmL{ zVYLpXmJy&pWO{{?P&zxcs|!4?BSR+?(1P*8KU# ze}~@qL-_{$>io&o?p0@g@4#2%#SeY&p2dYV>W}xob@zSc*UMLB`gP?$0ZIdG`bYmt z53g#2ji>UB$xwq?*ROH32>hR8GXGRxPr#4Ud5;> zT8}VZYu4*&tVcSU(I8B#AU?1Tc)kwbaZp3E8l7es`(-t{Pn~0a$56~Lu75nJl2yA@ zwCYJp12SF*pfMU0^cgrcP#QS_e;gT@{ud=vg)IY=ikmY@W`pnog0_*sMU6#E-jugV zCdnk$QM1Z6{8{_FH{RGea)jA7GJ*c~nX9iaKZ0jnugr1V=%@5G>@^_!Uz1}ucyJwW zwShj8aIn^p)uz>{jSjb9G_Ey!JZ=xP7#7S4TqFA<>iaw%%I$LBC)-4mf51>*M)d58 z(4k$nAsb~Q*q;GcF1I(69(#RdUQ6zy?vWC_>V~ZIbKxXVfTOtCkV&%22#RDpraU$m zP0CEeJUf9GM!jL04~hZNFZx7A#YK593*0UYg-TS{VXudgC}56277FXDy7pQ;h8#i! zkRuAXQLrc!!5Oe560C6ee=#721PqX1#xD=otbMfn`CZ?(Yk7*Mj^oFIl2@3_gl**w zv+kR?VP?;S@(X`mSX!J+KYs12-^28pR$9$#S^RtW#Ebu&3KY$r@43hIUcef4|AulAbzk=R1#Abw7Ad-hb2WmtTy9@^L%?oAH8?H$}&kaXlZb zjGBY*9c#Gg(evv!{;2%&t6K;>Fp7hWBzlhyt&zP~X*Tme;^<}EI({qnZ8gKIc^y*o zYH+@QG)T)1Geu!=#L#MNK$v0gLps>gA%a;3qz1w;=m}WbR(KEbE1u0_h@x?Of9q-imj+G}C4-cTo?%iXkfVY_ zHB}j(C|K3Nr!;AvAPeXh7Qd|ynSw@;KN&4(8dXqOedanWh)@uGI)_k%&f8O1*`Nn?pbP)3my8g*MG!x%tNWN2lKSL%JnBY301@*Uh+K_c%@K z{B_?R{>j?Q2I{&tK6%ZyqX)lt&4N}4t`q*;Jo-Al2jc`HHU0*oAa53H9 z^L&?kF86NsZ1&zQ-0s=oeOP!R@k-*ja6DnifAB7+(-jZWm}a%Eh?6w<$dq{oY#48F z^1G6(Q_pTeCTt>FTw1#&PGFo)RkS!ltgR;roenrp0)GRhrtmqULlbNSjuwhmsRVr# zz^NuM<&40}bTQE5GzlJH!obj`g=$IvS#Hq&#!zyv$X5#-sRT_(uBpe$%kJ$d6;UR=+;~te;qUX_TKgn zI$GZS&Yk5Kuli0`%ocZgs>dz)=S+8lP50LyzlE&|J%BCA-Vbo3ATBQAlKe1jqy-o4 zV$4Rf;0btwNjk|SR7JYT6jh}_DL6|rf6H+*eKWI#zd`*i{kII?GJZ?AIdF6EZu)L! zyMDW2yK%d4ci`?|xKrP0pg0J3B8T0MDW?-QmkTo<`o}84W7K;Lag7KMFb3@|%1I+& zS65(O9pqK2lo?J`YcvTnT&Z%=c5vT{tO2|18WrOVVn{AXIh@0ImaJ3DqME0Je?|k% zOKoZpt_J)9Na!9I4o#_1D0|B78X0jCZc+k%QgRa`3nUfH-WZt>Q9CB7pmr)ED@g z8>VkN`DuC4lqvJ^BXL~LH}{PEe|=7^)jVtDlc|9!cMpzH2C8=C*vNlJ)EEANK6(1` zbp=f%!aLH&iB&KBtlwR0)u|#dS-{66a3?&i@Z1R4^smcPZ}432ryA%Udah@h{}6r= zzm4BXeuO_sYBIba>OGNk*d%&vX~`E$s0AJGt7c8HbWLyd^53%f7c6Gke~2xevD+wJ zCLE6N5X#TXW>+6IQx0wlJ{zQiwK;XdBn(sZ-r7761TjSih0FOUX^FoiG_W+PSM z7?=ThwqgXt>ckr69FGCIe-II2LyDScGZm=voBueHb-7C`N1nTS{P?S>mM^imq`2mm zmp{1dk&(sJvz^!7KI0+T|NMk2AA58oE>m@Z2-munzIAn*D*A(;ez!O24eh-3FLScg zp97_P9+xG1b-4x{Hx$Z`egLtIMT%$TQQ7?)@5hc0opir*nUjk1e|87!QEilYkH~Su zxJ?eh4z)XK=Zs*i0xTukobjl`;Q+T_r{h`2FB~*z1FHQ|>B`C(E*XW`4hME6kwdY`J~eg%zcc>c)cOL$rll$Ca zu@|C97xETK5&obRf1rE~aAjiWOTmhXD2C`IpBj9%nxrM0Xy5qOugibNf%kUaFzNhg z=aNT%RzCFH{-Fal|FFe}&Ryz`CHQj3kA5)y!wT z*b9I;7}XmR7O z^-%@Hc{Jxhk_7dU@Z2x}Me!#@L2Iy?zCx~`gE3XuuLOo_^`yVt^Iu0FEPvKjUB3F# z&h|A_96NrBf6w2raq4;B|7hf;i-YrS1IK;S&Mp4@=|8X671zagGZNF#;b@4l7Ne`a{ACFS$`;|U%RF_EBM&UNZu z%{mmF8l|Gcl;&X497r%U0cNsljAp+aICbh&NkO(&QV{^36iyQI1@#;#7FP(E@JA$k zF@R5go=jHiv0Y+}5U~YzIgq49%7E%kAW0PQyh+(5R7>_~5j$3Qw69@guGYQuK>5?O z4L5zOf5)E7IeM-uzcA^@>n~0z4xE0BIzOTSaAgM{Eg#=9)fX=pCSP8TUOuVJHrwa! zDL()pgg;E|GG+nngwaFtoc{>M35a0Xzk@L#dZf5i0VW;rhXIV|;3x4^SOV4HU+UhR zW~%0O4Xq)-i=G3XLZk#xUk*$H;1SLAEabqVf2jZsz%>S@{{gQ5dtiaIaI9|vICXGE z+qy@}pClYOehyCWbgdhCE~0O}p1!;Spj&#qiE{vwSGTH(Pmn^@qaU)nflm=n@3XS! zV+zN4=}M3P$03*K@x`UDGb&E5t}v=>L~_w)z@nHglgk3LimAB;lFOM0=W@yLPU#mC zf0dP{NY6^NG)yu3Ym76Kgm2YUk10h11c^YV3Sh$$?nM9tun?NvpA)8qp>dM1u`#Ok z#xr_TB9e}p;)Ho+2=l5U%q#Ux=7s(P>r#}Z3f9?xg@KERImgB%dgaHaR79T^vaKEK zpL?PF7Or|XvN%0H+_9R{OmtP1cmAmSf97i+9()Op7lE0Dg5_yD#%}`Gz(eJa%Fh{$ zPAP=P4K{MoC~FNaF0TwCx{+vTyl#Ze_V=+o+>CMH_b$nEPuTeCDF;( z$=a*oy%dTe+{(V%IJCL z9&5%8Z|vrgGw7V^q@9E{c$HTseAVkY$5+8R02e-RQc!>h8&xLfo6Pd;T=;Q5sIW(c zJ5n91Cplt{d^a{7nNz#?^uDi{VN}&};hA_S#?sWB!{zUve<9~Vqt&Ls!Q<7a)d{oT@AG>!5S!3*9-S73gd_)T_1L|> zaD=t-vRCxk;<~uW9(RZ10X`my({KZymvsj`?t}m)5pyu+52PycL~&v$EK!*;Ao$Ne z7r^raRdd$;vfGJT9ip@k?_AT~z6KP$=8;q0k&)`)s&XKr@Bbk!uj)`mPyd}!NBNGGV_2%` zx{ki{^cv=ZGrxE+FY16vf;=AmgnbZT2i6X{Q*Qr_6Zg56y584*YWURlkyoW9Mu*Gg zbZMQui{X()0L9L%f1&)y6X2a{QKaoohsLcn#dX@0!(omqSgey=fw()xsN=!7B5kD* zV8!R3mqtDZnen+2*!lddfCbEMJwxC!QX;5M#7A@1$q8&yU;r#cMNz;K%U}?%82tN0 z%qqY+2N4V)@upi_@jTjABd*53zihH}W>A3!^_l{Y&0?L4e~O-oQja~97d6qSZqDx0 zuP}?w{6T>PAqs_VnOV>@K&t{a7ENlEp-aNtRiJjHgLZT;{mdqi4 z%tCWw#-Gvja^twDgI1KdSd=%+6g)Z4R1fVT1d>pN#MfBCd}MCl?ps`VLWVaf%C-m94fp-+0&SE}u`X#C9evRWPB<{_R7idb=* z6MRBr#sJV4=y-LI6*Z=%1i^4%z$+nDxF0?E!`auj`U)Z8mTBA1JaSoM+a;72GuT>w z?PKvG*SM=jo@cgqM_tL0PgyEH{^c{1wd1a#FJIBAe~!L#{~J%y<(t=)h|mQ;M0q>A z1L9s<(C~gMXCuxBw67SR6P~lb68?GQUBjEgoA!6Z??!a5SYL_##`=DYna0Z=kLY#q z86!oR#kqr{1ona@!m{}77320G?9d0BtjsSJcr|_ln4+IG~hZAc&mcs*@2_P-&>({C^rKS+#r;QYoE*_ z1jNvQGHGVJlTkS$Y*b|jglC)_U_F@xfAGSQXy4cE-LG)FhQvZtT*c{txeA6;>*oFF zw#nDdj+HkJHny#z3VR2C_tGQyf!O5c@}aVG4XBhaQ7=S04)1G|T$wUAvQ*o>iN5^e z4s|p=>%?96xkvt)OQ|B%AX{F!rdgxl`mE89=#zl!kUN00a?~WP*IcFDs@h*#q5{i4cg3IHEzJp$m-_r+nc3w6XJVGw{ z=j13jsEYM{p<#UW<4DK}lu&HQe;#{tV8h81PH<2Fd?#%<={)6hgL^a!dxYZ_1=s%^t@jf!!9P> z3`=0{-8%i&t5+?akiB4KO@6^;_q^5>7RwV~xOY+Cl!juZ+dnkv+ z1j#NuZ_=wQ8Hg?Eb-WAcVjtCuhcPc3I6h$xnC6*wn)a9&6LjrEy^h1+lyhdm1cj(q z>C~xnUVcSmQpf?lS5jf$lw80elkY&=qKDd7-IuuPTrA&>{%pWt1F0tIIe-L zVBDZ-sOhh}$hFLKx$6qg4zvUBH0~7cNB83g^m~kt2@gabh#o)(@RP~?#!nM?v| zS6xj_0{Z#7nrfbD$Ys(ltwyExR7Ko%xhhD0CHbzJnubUif4DVOQ=Lhx8zCGY8OGfQ zg2;{CPlAJV6H?>nWK9q?Y-*qyT*by={D=MGrROW*`2n|U(umtR0`-XVY?xkgpn^UJ zO1a|OgBq0F&66@o14L%n&EP!!pA8bU0saP*N3L-@6-Vm-S;2uX6`ZPk$xz~-i*aA9{q7@M{5IWQtSE*IZIzV@|h8}SCJDw^qEJvZr{P+YN~ ze{|8T3*#MbPgYmt8|?a~aQ9ssyS`ms)o70yJhd@bw6D26SigRNg2gFBXW<||`ZTOx zae~Emi(K`E4y$zdZatQGeB3q_dGR($72zOrRb|uCNNmw^o<%0Dztb>GK_D4aI91kq z#D;B<4_pZz1Mh?xsYLroCf8ZuBPEAMf0+WOH>eYWI)4;<1tkwJt)WAa;~$QaZ|3Ho6{e?d6Ko*kf4=snj?5{tP^uFh_I>Ha(Z(ixj&x}y7rFMst5 z49gY>epCZ&PO^iLrP+wyl~>*we<=QH{AZ~TQ>RiYv@&yb=BCU&nMab3e`cOYKAHJ> z@>u4@hWC>1X5MNr(8-AjO5(N0nW-ADcALo`bWHVm{kMrVka)v5m{6=H3syc`+sK&H zCS03ObB!&rn5YdgS#wNQG853DQlaw)RT$_W?=3X}2nR?s`IO>vg2>Lv3WhmAb5g>c z-~}d`T4PlO+3Je%R9&hNe?`SO6!pp4C~inJeht}_2r>i$9cPodz{DkRgaic}U2zuM zR7Nm(6*8sjYR!3b{aEG~iHuU2=6J-D*O>#;({n;XL`7kW3U+DjTGdV8=Nb~@=Rf?b zk;m80zo~uW%{#tF?+w}_xTQHm(V|V~*0Ba^S#f>SnP0TkVoIcPe@*JEn%!y4J@y-1 zIP>873H;b~D}MW<-DiOJ#z#MaRXh)aFN#=OD0 z!FI;*rBOeNzmT7AI?B9cev|oF{Rbo8OwvG{;5MPu8d?R4CB&D<(JHTZkM5zjUg?bE$s|+5* z+9K|#)vRz-2p9OV%gGw(D6*Tp(8f?OMwK!PU`3qer)NV$Hj!A#Fb9x26H*`!u;)Y) zDk@M5-yFGK^UQV2wlzzM-~Z^Tpa0jhkCuW4{D9U|y*5ohfBgLZPu{#_iSC+ru=nuK zaCrQZ`ss_S`^JNw6^G!Y0Jt1Qm&=8M1_HV+O#*-srCX6V`axK1^+rCBXpxOt>`v1T zXI_f~Y|-!IRH|r1L;Hhq42CXo4En?@mjwVGhIQt#tfDU-`(mIdR2+k#Jrdih!ux<` zox)MDd(Zilf26uR2$`N#(#_bTArBRuD74k6 zVV_Q%r=AAd9Ccp4Cyx2E7 z=B}6>^6!2r8%l>~bPD#IeVcukoq^Qa(Y^hB*<&M0QV5td$KD(vxgmf!1gBb$f!}HH zy@5f3e^FT_|85MmD(+;+&w{)W0!A~Do{CBZekk}SxkF|psY)?hny^heYpcX6#!DXj z0TnL`7&on;cagJ!$l)&0O6rk4Pyg)cD<61$X6<()(?j-!PF*$^Tk^!iNb5 zqRYUx%Jo$2?)jJfvWuQp6=b6W>X*@>0fO1=PsZ3 zUjx-WS3XDe0=}97Uq1rboI{6XdzT&m(}C3vw*&mWLN<`2q*gDiZa*zIg$VxUf?;>7 zf7c(BlC9osP&&(Y6H+pnklZF(70WS#&4^+xHZGS9_%&e(0@9#Y9jXyx$t-wIVRn?r zi6X!OhXI+1li)0iB`R`7h!d>`ra@t^knCo6M(tt9DsV;|F+Z3>K+HhLgsYCZP>DeV z!n_qbD#BdRfXdphwf~2pTt&)7*!_NAE`1z%3c%_!j0glN5+`hk4;quP>CZ@R8%%a4gUJz zsfsRgR!jl_$ovxkoKu8_8jOnd!GhRt?ay5lT%NnjrV&G-qS+dfY*r~Ghh~_?YOAd}XUkcut8=ha z6EyayzoNMqksko7LiGtcf9h>0#5A^QI8OVd92Kka&5v!09f{Gg#sZ;5t+hJa5Y!$& z0>Xh1RAZ6oEGJHYZ2}ITqa-Q@|IJy&2dBg!KvtYOd4?Q-Ug+m|!JTwNEP{tv#5Y3` z3LPn!1o>>H2;kS*Aes?FZYl9U5Q>A&v(X7=eseBu@tWpb)RTe*e-GH^x1}5L?n}4) zwCV77woNN{NG1rtlwZmF$CpJfS2KhDbX=68yiSkP$g0mge##TnIdrtw%k}Q9|I6@t z&h4eJ&Y-pE@SWxFbb)yG1MG?(@vmYa+3hx*rpZWqBu|hmm1MOOCvq5xieukq< z7nHqTb#Vs$M!Ty@r4qv>o%Qsz*?A7A1e2T(RW1D>tYrU}?5%gz1}RhU#|COjVoHe; znuJM#$#iQW-Qi6<1K*ViAsMVaFDk(-P7E=P$U8Y04mWz^e?h6x>TL>2;~Tw`f|4%C zPK6=eX6zX6Dahk{I^;rqI_$BsjIL|4#aPqT;;3l}1RO?g@}yEzBCeTA7>O3BE^}-8 z^)%I!9>(KjeYad+$hO@ozb;cfGW0y&%~)dNv#bJ@DFiAfguzpT15Nq0{JeIcE3_Y=ZEK4ogHu0k7plw27-lE<0f!68e=Gg^X?$u9m*?GHzJ3PY zvmi4)=_-`bw3)Qqt?RrVJMV5>*ik?7{=`P?Cj1=cmHv?aiLzSkak<~+p5&%(H#}ef z!59#Qnm|4)wu)?|)hh-=1R3+eu(#103`$`8)Q~BxV5KpWj(9B$&E?I;M2jP4?&-HOSq{HN*o`fT9HxT4O|q_!9mcU{2I=hsf2 z+1YS$V`q8R_(u7>rshz++*R(y?|IdA=K~hIe}R%ET}?ov-hN)NIyUk7a=J&xUazM4 zLj1^itK*Kkk=J{wDK9{hMzy2A2c7X@kdb6P-)(a0MfFE&>UQBS`!3-T`xhG4j;xHs zF-tR3U>kX7-bHcdJg;@xI$c`G9H$O>jGab^R1j;y;~q2A%tggmfXoX894X|`M|9X2 ze?<=37R4qtv@9I749FS9b_NPTV~)ZnXP_WxT#4~0y2OARP!>T7DrAsD@+x@Nlw5I0 zPc77ry!0Yw&b)l2{3Y&hT)g|%OV{6hTZFm;TgqqNc?t5w-EZL^)Xx3wzVflxe*74& zDG?k}D?0LC$P3S-qjG<}x?a59bywu!f5`o@6R|I1ye7iNCPe55!niApL%h(T_vVj> zGacTV45^ko-yDTMh921Z)riwAVM}e_5KOJ6TB5J5mp24rh*KenWkd`7*^#O5p}R(%}_9 z2ze9&g^Xud%wwfJDo4%}sS=}Bo@NA>Q0@O@uJIU z0OA%6P%ZJhK*$mP#uVG|Sh|lwzr+V%25t(H84}FL@&XjjIp)^`PYi{oNja-Cz2Q5X zZ`?SyRvNcT4cyb>n^E@m&+g98T(;qLjDNmDu(;y|{J@md)X(nNdz|jH=;G}RW*F^h zxy~Kqy&`U0j5l=otN-}Bf7eLR5n=}b?7aZz1ll4`JnF}V5Dp|T;d%)WUmZkzX@g8F zcwlZ5LIFRW42MG?j1yL$CAi6lgT9=P^6l^mF$V|2Y7_Y1la^SxVh$YG0~83kc>{_# zIyyjLI_bo*ldHiEpe&YAAbJj2@mYzZ2n~XWMC%8roRv6Z4l4yif35a{O;n#>id1Vv zbMXpCO&v$em&TC3C+r$)H1e{pjr(a^oRRBk@6 zg91T7aBb=6N$O|xUb2E1)3Rtm7Hp>y`l5cRZkc|)cD-(k4szUc-s(4i{lPWE_`Ca| z4U$-tjiD;1*Y$?%fANa$0F0g-gI(}vigHpk>yd_sco)O~*+9O=%(3|@ZH>{5|Lh)h zQ|@lQtp?>{I93ZGzQ4%=id|~lWjtb}joqjgJX!#{!8e@)Cr*Oy2fT3b=)h{HV(CI6 z?N@TUl8yG!fRc_@Nv4G^i1~e_q}P(*pTY;c@kCIB<*J-2f5H24&=m3`F3$RqCFC3Nn=Y7_CT2INRJ-YQ}LbMy;$7wPD#0 zOT($G)#H>+DJz(z$KHb^o%fny5z@%fW6%`dh61&Y48G}hzU*#2rletkCxApsk8lo{=LHV_l($ z-QV4~thj`_fL5^@t+hDrPDcMF!7Z}J_AQW$WTpCp^5kBwH!z2r6IjWu46Ntw;qD2j z1Nwl0^6{ERuOTQ!8@bFoJ6h z9n2uee+`Qgxj`9YD_8$Ca`UfMMIujGqt`tP4a;!Kae|P3-uhD2#ht#Uw(_*ET=4})=)nnqk zI>M780JGQW-AF?B%NNA7FFaFOXE$5P+r>dWm{_&2LJ z+qd}dLU&;Y&+%$?(F_R8JM0`cLrD$e)DR1Eg+hXb#$E{Qy0j4<63gtAc^IELG|u7Y zefpOs>Vsk7| z2hhR|>!g+YOHmTOWen9Vt*dcCFolKN}%R?5MfiJ%nsdDA$-2s&~B>21|r|~Od zk0oYO(}4g}yl5n6F*r=rd;LMPO8G1Te@0cKpR?Zq_%uQ!`i3YM%@u7$Pf=_Psni^N ziOX%C(O{ziJ= zCXxc2d0zuKL`;t!O$tXL(N5rxf^iE5E@=T7lk5?I^;a_hQPDg>S26)nh?FW7FtV{! zGm?1c!38jLl`eX?)Tq}U+Nbkoe^O;v&{safs8l-Y59NPS9IK#0w8V_fBd9vS8}2|&Sdb6@k;CwbFHAm+ffH1g%K7U1#J*6Ue>4GB2C4aI z-^^@g4|xyyUQm4;Gk0@6#vWmugQ>48NOc-srKwXnc#Q@kFt&sWhNf~PZ1F@vf)cj+ zLY<}{*@|XOqG+yz({5MYuR5f9Tg5oCW=REGK`IpL5|YEFQSmj6*l4C3y@IKUMk-&n zhIV_sxoR4g8mKfjrpaU)-$c%BGJmN&)kKAAt}bO?eD6g_MR63fkoZPwk{x*lvLls} zbYwCdBmgD{poWUfoicsGQ6AP9!3L8$HlvEeLYYs6q$(!n*Sr*Ci;om91!$o#eNO^N!^(`oceXj z(38Tkq$ZVAa#)LIC#a`t^?wX=DwRyBwN4it-&P2Xl;JofY?H z#SsJmjd<|`HO`Di|LIdSeB(8MEs2D&{KE9x*ETF{O1m$zH(ae^%6~^f`5OEleMbQE z`l!L@8~G=tYW$0g_U?HPnF#5CW;_U+~RhdN#n1d>iJ+ z^7#(xMT*kSFk^^=%`j^;T7kn{cL2D|c#gsXe7pc_P1>SKrGZ!!Ra9%t9Asv}T3%V@ z75SLV?cpeHyj9mK8-KmQ zK6P=sUSil}xo_l|IxNDdnqZrqJF5>y5c$DCiY-Sn?Vq0v5(R#aLmH z$K&Eu?QL0@t5{XOHXDgmxjUOmGZ=b1>+0wn#?$wUtM@BOFq4R;03T+7Pn0Oj8!B!g z;+r@@EFTh6A%CPxHsT+Gf1hp=0nyxQTkJ8e!{WmUVP$jMv4s05Y&+G`c> z8w9HA!OH%cq6oxFphnzB&}$@I`|FM(A}L84E6}}7Y@gh6>#fxLzn{M=DQ2$h89y^@ z)!}etAgG?CW;G1PxM^CsWqu~nUF{rqL((&;+~TF{mw!{YH~$9HeWgJ9k?M|`mEU6+ zEbv-&b(Ou!KJuq!4H~as4QF}BMQFIi$h^6tjd=TruGX&1$ts}Y68g2gG|I<2yb{a` ziH;l(`y0I>h>kSEL`n5^`5Kd;YI0S(z5Zm}Pcv)|x~iFi%Iz@=F_-zTg}gE5LJ785 zY68)k%YRBCO}skmjrrXzO|hiv#i}YWA7iwuxn&qn+AlsgHZ9=k1=rk(v6)dEcEm?S zyu2eH39yjv8`A=FQduTZQSciYc|$P*=~28EzQ?QQSyh9f$&VU&Ff7TufPQ~&Vu&AD zi6Vkx-wKKgoMJqig$4)eV2OpoSBdll3xErKr! zs2NOG&n%Cd=!}*(lxCL;)M3tOEX^&<_n7e}uTVEgZEU`xabSEdl&__zD9vD%MnC8D zp2;<8;H4J-Eb76LiEYiCm)WaQeRtjXKUU_0lnC;RmMD#XFPfo)d}m5f)@G3JNmafj zRe$-C)c^cW6yeU*U;9E-Bg}Uve6zG0je|Jncr-!zHs>Vp_D+EhWluxX;VYUm(JUnb z+6Uj$oP*}VH$w-|5%g1dGKsEX<&{(<&eqj6t!KjYWN%_>3NbVwFd%PYYLjiTjs`L?GchtVvjMU*0z)-sWHB`{Ff=$Z zHfCjGWivJ~Vl+82GdM9aW;8c4Fl0UoJT+!yF*PwTG&nIfW@Te#Gd3_{G&wReI59G2 MG&eFZWRrKa9sG$p@Bjb+ delta 18041 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 MWiw?qFq3z*9fcq2O8@`> From 7f55cb18586e5e7abfaf03480f344a270f42aabb Mon Sep 17 00:00:00 2001 From: Joshua Miller Date: Wed, 19 Oct 2016 07:42:28 -0500 Subject: [PATCH 19/37] wip --- esbuild/graph/common/builder.py | 48 +++++++------- esbuild/graph/common/cache.py | 113 +++++++++++++++++++++----------- tests/test_suite_data.gv.pdf | Bin 46228 -> 46222 bytes 3 files changed, 102 insertions(+), 59 deletions(-) diff --git a/esbuild/graph/common/builder.py b/esbuild/graph/common/builder.py index b3a2d5d4..c900cf58 100644 --- a/esbuild/graph/common/builder.py +++ b/esbuild/graph/common/builder.py @@ -689,8 +689,9 @@ def get_exp_strats(self, files): experimental_strategy is non-null """ - self.cache._cache_experimental_strategies() - for exp_strat, file_list in self.cache.experimental_strategies.iteritems(): + + exp_strats = self.cache.get_experimental_strategies() + for exp_strat, file_list in exp_strats.iteritems(): intersection = (file_list & files) if intersection: yield { @@ -704,8 +705,9 @@ def get_data_categories(self, files): data_category is non-null """ - self.cache._cache_data_categories() - for data_category, file_list in self.cache.data_categories.iteritems(): + data_categories = self.cache.get_data_categories() + + for data_category, file_list in data_categories.iteritems(): intersection = (file_list & files) if intersection: yield { @@ -1052,10 +1054,11 @@ def add_data_category(self, node, doc): """Add the data_subtype to the file document with child data_category """ + cached_data_categories = self.cache.get_data_categories() data_categories = [ data_category - for data_category, files in self.cache.data_categories.items() + for data_category, files in cached_data_categories.items() if node in files ] if data_categories: @@ -1074,11 +1077,11 @@ def add_cases(self, node, ptree, doc): log.warn('No ptree (case tree) for %s', node) return [] - if node not in self.cache.relevant_nodes: + relevant = self.cache.get_relevant_nodes(node) + if not relevant: log.warn('No relevant cases for %s', node) return [] - relevant = self.cache.relevant_nodes[node] prune_keys = ['sample', 'portion', 'analyte', 'aliquot', 'file'] self.prune_case(relevant, ptree, prune_keys) @@ -1152,20 +1155,20 @@ def add_file_associated_entities(self, node, doc, case_id): docs = [] entities = self.get_file_associated_entities(node) - for e in entities: + for entity in entities: - if e not in self.cache.entity_cases: + case = self.cache.get_entity_case(entity) + if not case: # Skip, the cases is likely missing because it is omitted continue - case = self.cache.entity_cases[e] subdoc = { - 'entity_type': e.label, - 'entity_id': e.node_id, + 'entity_type': entity.label, + 'entity_id': entity.node_id, 'case_id': case.node_id } - entity_submitter_id = e._props.get('submitter_id') + entity_submitter_id = entity._props.get('submitter_id') if entity_submitter_id: subdoc['entity_submitter_id'] = entity_submitter_id @@ -1186,7 +1189,7 @@ def denormalize_project(self, p): doc = self._get_base_doc(p) # Get programs - program = self.cache.neighbors_labeled(p, 'program').next() + program = self.cache.neighbors_labeled(p, 'program')[0] log.info('Program: {}'.format(program)) doc['program'] = self._get_base_doc(program) @@ -1216,11 +1219,11 @@ def denormalize_project(self, p): len(files), len(case_files))) # Get experimental strategies + experimental_strategies = self.cache.get_experimental_strategies() exp_strat_summaries = [] - self.cache._cache_experimental_strategies() - for exp_strat in self.cache.experimental_strategies.keys(): + for exp_strat in experimental_strategies: log.info('exp_strat: {}'.format(exp_strat)) - exp_files = (self.cache.experimental_strategies[exp_strat] & files) + exp_files = (experimental_strategies[exp_strat] & files) if not len(exp_files): continue @@ -1239,9 +1242,10 @@ def denormalize_project(self, p): # Get data types data_category_summaries = [] - for data_category in self.cache.data_categories.keys(): + cached_data_categories = self.cache.get_data_categories() + for data_category in cached_data_categories.keys(): log.info('data_category: {}'.format(data_category)) - dt_files = (self.cache.data_categories[data_category] & files) + dt_files = (cached_data_categories[data_category] & files) if not len(dt_files): continue @@ -1323,7 +1327,7 @@ def denormalize_cases(self, cases=None): case_docs, ann_docs, file_docs = [], {}, {} if not cases: - cases = self.cache.cases + cases = self.cache.get_cases() pbar = util.get_pbar('Denormalizing cases ', len(cases)) for n in cases: pa, fi, an = self.denormalize_case(n) @@ -1345,7 +1349,7 @@ def denormalize_projects(self, projects=None): """ if not projects: - projects = self.cache.projects + projects = self.cache.get_projects() project_docs = [] pbar = util.get_pbar('Denormalizing projects ', len(projects)) @@ -1446,7 +1450,7 @@ def validate_annotations(self, ann_docs): ) def verify_data_category_count(self, case): - for data_category in self.cache.existing_data_types.keys(): + for data_category in self.cache.get_existing_data_types(): calc = len([ f for f in case['files'] if f.get('data_category') == data_category diff --git a/esbuild/graph/common/cache.py b/esbuild/graph/common/cache.py index 7f0728bc..3d4a4635 100644 --- a/esbuild/graph/common/cache.py +++ b/esbuild/graph/common/cache.py @@ -108,7 +108,6 @@ class CachedGraph(object): """ - @classmethod def __init__(self, caching_options, psqlgraph_driver_args=None, psqlgraph_driver_kwargs=None, psqlgraph_driver=None): @@ -137,22 +136,6 @@ def __init__(self, caching_options, psqlgraph_driver_args=None, # ``self._cache_existing_data_types()`` self.existing_data_types = {} - - def iter_database_edges(self): - """Returns an iterable of edges to load from the database. - - Eagerly (with join) loads the source and destination of the edge. - - """ - - return itertools.chain(*[ - self.psqlgraph_driver.edges(subclass) - .options(joinedload(subclass.src)) - .options(joinedload(subclass.dst)) - .yield_per(int(1e5)) - for subclass in Edge.__subclasses__() - ]) - @staticmethod def warning(*args, **kwargs): """Log a warning to logger and statsd""" @@ -170,6 +153,27 @@ def get_cases(self): return self.cases + def get_projects(self): + """Proxy to get cached projects""" + + print self.projects + return self.projects + + def get_experimental_strategies(self): + """Proxy to get cached experimental_strategies""" + + return self.experimental_strategies + + def get_existing_data_types(self): + """Proxy to get cached existing_data_types""" + + return self.existing_data_types + + def get_data_categories(self): + """Proxy to get cached data_categories""" + + return self.data_categories + def get_edge(self, src, dst): """Returns any information stored about the edge between two nodes""" @@ -306,6 +310,28 @@ def remove_unindexed_nodes_from_graph(self): logger.info("Removing %s suppressed nodes", len(suppressed)) self.graph.remove_nodes_from(suppressed) + def iter_database_edges(self): + """Returns an iterable of edges to load from the database. + + Eagerly (with join) loads the source and destination of the edge. + + """ + + return itertools.chain(*[ + self.psqlgraph_driver.edges(subclass) + .options(joinedload(subclass.src)) + .options(joinedload(subclass.dst)) + .yield_per(int(1e5)) + for subclass in Edge.__subclasses__() + ]) + + def get_fake_node(self, node): + """If we've seen this node before, then return the FakeNode version of + it, otherwise create a new one and return that. + + """ + return self.nodes.setdefault(node.node_id, FakeNode(node)) + def cache_database(self): """Load the database into memory and remember only edge labels that we will need to distinguish later. @@ -321,7 +347,8 @@ def cache_database(self): for edge in self.iter_database_edges(): pbar.update(pbar.currval+1) - src, dst = FakeNode(edge.src), FakeNode(edge.dst) + src = self.get_fake_node(edge.src) + dst = self.get_fake_node(edge.dst) triple = (src.label, edge.label, dst.label) needs_differentiation = ( @@ -333,20 +360,16 @@ def cache_database(self): # centers and aliquots of the source files count # as neighbors of the dst files for center in edge.src.centers: - self.graph.add_edge(dst, center) + self.graph.add_edge(dst, FakeNode(center)) for aliquot in edge.src.aliquots: - self.graph.add_edge(dst, aliquot) + self.graph.add_edge(dst, FakeNode(aliquot)) if edge.label == 'relates_to' and edge.__dst_class__ == 'Case': pass elif needs_differentiation and edge._props: self.graph.add_edge( - src, - dst, - label=edge.label, - props=edge._props - ) + src, dst, label=edge.label, props=edge._props) elif needs_differentiation and not edge._props: self.graph.add_edge(src, dst, label=edge.label) @@ -360,11 +383,6 @@ def cache_database(self): session.expunge_all() pbar.finish() - self.nodes = { - node.node_id: node - for node in self.graph.nodes_iter() - } - # Prune graph logger.info('Cached {} nodes'.format(self.graph.number_of_nodes())) self.remove_unindexed_nodes_from_graph() @@ -446,6 +464,16 @@ def _cache_entity_cases(self): pbar.update(pbar.currval+1) pbar.finish() + def get_relevant_nodes(self, node): + """Return the nodes relevant to this one""" + + return self.relevant_nodes.get(node, []) + + def get_entity_case(self, node): + """Return the case associated with this node""" + + return self.entity_cases.get(node, None) + def _cache_relevant_nodes(self): """The file documents will need to be pruned to only the nodes that are relevant to the file. Here we cache all of the nodes @@ -473,8 +501,11 @@ def _cache_relevant_nodes(self): def _cache_popular_neighbor(self, node, neighbors, labels): if node not in self.popular_nodes: self.popular_nodes[node] = {} + self.popular_nodes[node][labels] = { - n for n in neighbors if n.label in labels} + n for n in neighbors if n.label in labels + } + return self.popular_nodes[node][labels] def _cache_data_categories(self): @@ -562,7 +593,16 @@ def nodes_labeled(self, labels): if node.label in labels: yield node - def neighbors_labeled(self, node, labels, expected=None): + def neighbors_labeled(self, *args, **kwargs): + """Proxy for self._neighbors_labeled which was original written as a + generator to return a list instead + + """ + + return list(self._neighbors_labeled(*args, **kwargs)) + + def _neighbors_labeled(self, node, labels, expected=None): + """For a given node, return an iterator with generates neighbors to that node that are in a list of labels. `label` can be either a string or list of strings. @@ -570,6 +610,7 @@ def neighbors_labeled(self, node, labels, expected=None): :param is_expected: Int count of expected elements """ + labels = tuple(labels) if hasattr(labels, '__iter__') else (labels,) node = self.get_node_in_graph(node) @@ -579,6 +620,7 @@ def neighbors_labeled(self, node, labels, expected=None): node, self.graph.neighbors(node), labels) else: neighbors = self.popular_nodes[node][labels] + else: temp = self.graph.neighbors(node) if len(temp) > 200: @@ -657,7 +699,7 @@ def is_omitted_project_or_neighbor_case(self, node): if node.label == 'project': projects = [node] elif node.label == 'case': - projects = list(self.neighbors_labeled(node, 'project', 1)) + projects = self.neighbors_labeled(node, 'project', 1) else: return False @@ -711,10 +753,7 @@ def is_node_unindexed_by_property(self, node): def neighbors(self, node): """Return the neighbors of given node""" - return [ - neighbor.to_json() for neighbor in - self.graph.neighbors(self.get_node_in_graph(node)) - ] + return self.graph.neighbors(self.get_node_in_graph(node)) def walk_path(self, node, path, whole=False): """Given a list of strings, treat it as a path, and yield the end of diff --git a/tests/test_suite_data.gv.pdf b/tests/test_suite_data.gv.pdf index bab9386f2b842a29dc17110b0ecebcd6e6ac4715..54567ec725040ec3529cdcbac9f33bf2898fbabc 100644 GIT binary patch delta 18159 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 S1W8?bT6QR~g@wDn2lzjWF-#-? From e2ab1d86dcb6f390d0fb3228154ec28cc904c918 Mon Sep 17 00:00:00 2001 From: Joshua Miller Date: Wed, 19 Oct 2016 07:45:23 -0500 Subject: [PATCH 20/37] wip add fake node --- esbuild/graph/common/fake_node.py | 46 +++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 esbuild/graph/common/fake_node.py diff --git a/esbuild/graph/common/fake_node.py b/esbuild/graph/common/fake_node.py new file mode 100644 index 00000000..d0083eb4 --- /dev/null +++ b/esbuild/graph/common/fake_node.py @@ -0,0 +1,46 @@ +# -*- coding: utf-8 -*- +""" +esbuild.graph.common.fake_node +---------------------------------- + +Create a smaller, faster, serializable psqlgraph.Node replacement + +""" + + +class FakeNode(object): + + def __init__(self, node): + props = dict(node.props) + sysan = dict(node._sysan) + acl = list(node.acl) + label = str(node.label) + node_id = str(node.node_id) + + self._class_name = str(node.__class__.__name__) + self.node_id = node_id + self.acl = acl + self.label = label + + self._props = props + self.properties = props + self.props = props + + self._sysan = sysan + self.system_annotations = sysan + self.sysan = sysan + + self.__pg_properties__ = node.__pg_properties__ + self._pg_links = node._pg_links + self._pg_backrefs = node._pg_backrefs + self._pg_edges = node._pg_edges + self._dictionary = node._dictionary + + for key, value in props.iteritems(): + setattr(self, key, value) + + def __repr__(self): + return '<{}({})>'.format(self._class_name, self.node_id) + + def __getitem__(self, key): + return self.props[key] From e49d47d569f676c5b1a4a91e49620ac000eb0587 Mon Sep 17 00:00:00 2001 From: Joshua Miller Date: Wed, 19 Oct 2016 14:23:26 +0000 Subject: [PATCH 21/37] wip optimize loading --- esbuild/graph/common/cache.py | 49 +++++++++++++++++++++++++++-------- 1 file changed, 38 insertions(+), 11 deletions(-) diff --git a/esbuild/graph/common/cache.py b/esbuild/graph/common/cache.py index 3d4a4635..b2fbdb56 100644 --- a/esbuild/graph/common/cache.py +++ b/esbuild/graph/common/cache.py @@ -32,6 +32,12 @@ logger.setLevel(logging.INFO) +def is_case_cache_edge(edge): + """Determine if this edge or edge class is just a case cache edge""" + + return edge.label == 'relates_to' and edge.__dst_class__ == 'Case' + + def to_node_id(node_or_node_id): """Returns the node_id of a node if provided a Node, elif it's a string, assume it's a node_id and return that @@ -323,6 +329,21 @@ def iter_database_edges(self): .options(joinedload(subclass.dst)) .yield_per(int(1e5)) for subclass in Edge.__subclasses__() + if not is_case_cache_edge(subclass) + ]) + + + def count_database_edges(self): + """Returns an iterable of edges to load from the database. + + Eagerly (with join) loads the source and destination of the edge. + + """ + + return sum([ + self.psqlgraph_driver.edges(subclass).count() + for subclass in Edge.__subclasses__() + if not is_case_cache_edge(subclass) ]) def get_fake_node(self, node): @@ -338,17 +359,26 @@ def cache_database(self): """ - with self.psqlgraph_driver.session_scope() as session: + nodes = self.nodes - pbar = util.get_pbar( - 'Caching Database: ', - self.psqlgraph_driver.edges().count()) + with self.psqlgraph_driver.session_scope() as session: + # Meter the progress bar by nodes, because creating the + # nodes will be the majority of the time + node_count = self.psqlgraph_driver.nodes().count() + pbar = util.get_pbar('Caching Database: ', node_count) for edge in self.iter_database_edges(): - pbar.update(pbar.currval+1) + pbar.update(len(nodes)) - src = self.get_fake_node(edge.src) - dst = self.get_fake_node(edge.dst) + src = nodes.get(edge.src_id) + if not src: + src = FakeNode(edge.src) + nodes[edge.src_id] = src + + dst = nodes.get(edge.dst_id) + if not dst: + dst = FakeNode(edge.dst) + nodes[edge.dst_id] = dst triple = (src.label, edge.label, dst.label) needs_differentiation = ( @@ -364,10 +394,7 @@ def cache_database(self): for aliquot in edge.src.aliquots: self.graph.add_edge(dst, FakeNode(aliquot)) - if edge.label == 'relates_to' and edge.__dst_class__ == 'Case': - pass - - elif needs_differentiation and edge._props: + if needs_differentiation and edge._props: self.graph.add_edge( src, dst, label=edge.label, props=edge._props) From 81772c33dbe5e42d97f5e11cf055bbcb66be639b Mon Sep 17 00:00:00 2001 From: Joshua Miller Date: Wed, 19 Oct 2016 18:57:48 +0000 Subject: [PATCH 22/37] wip --- esbuild/graph/common/cache.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/esbuild/graph/common/cache.py b/esbuild/graph/common/cache.py index b2fbdb56..070ac701 100644 --- a/esbuild/graph/common/cache.py +++ b/esbuild/graph/common/cache.py @@ -309,12 +309,16 @@ def remove_unindexed_nodes_from_graph(self): logger.info("Removing %s nodes from cache", len(removed_nodes)) self.graph.remove_nodes_from(removed_nodes) + for node in removed_nodes: + self.nodes.pop(node.node_id, None) logger.info("Finding and removing suppressed nodes") suppressed = self.suppressed_nodes() logger.info("Removing %s suppressed nodes", len(suppressed)) self.graph.remove_nodes_from(suppressed) + for node in suppressed: + self.nodes.pop(node.node_id, None) def iter_database_edges(self): """Returns an iterable of edges to load from the database. From 18168e1e014cd1548484ee3ba5a1402533dd4a17 Mon Sep 17 00:00:00 2001 From: Joshua Miller Date: Wed, 19 Oct 2016 17:31:44 -0500 Subject: [PATCH 23/37] possibly serialization equivalence issues? --- esbuild/graph/common/builder.py | 27 ++++++++--------- esbuild/graph/common/cache.py | 50 +++++++++++++++++--------------- tests/test_suite_data.gv.pdf | Bin 46222 -> 46227 bytes 3 files changed, 41 insertions(+), 36 deletions(-) diff --git a/esbuild/graph/common/builder.py b/esbuild/graph/common/builder.py index c900cf58..8aeb8292 100644 --- a/esbuild/graph/common/builder.py +++ b/esbuild/graph/common/builder.py @@ -66,18 +66,6 @@ def upsert_file_into_dict(files, file_doc): files[did]['cases'] += file_doc['cases'] -def build_index_serial(builder_class, graph): - """TODO: docstring - - """ - - caching_options = builder_class.get_caching_options() - cache = CachedGraph(graph, caching_options) - builder = builder_class(cache) - - return builder.denormalize_all() - - def build_worker(builder, case_in_q, result_q): """TODO: docstring @@ -129,6 +117,16 @@ def build_index(builder_class, psqlgraph_driver_args, cases=None, """ + # caching_options = builder_class.get_caching_options() + # cache = CachedGraph( + # caching_options=caching_options, + # psqlgraph_driver_args=psqlgraph_driver_args, + # ) + # cache.cache_database() + # builder = builder_class(cache) + + # return builder.denormalize_all() + # Create managed cache caching_options = builder_class.get_caching_options() @@ -1332,11 +1330,14 @@ def denormalize_cases(self, cases=None): for n in cases: pa, fi, an = self.denormalize_case(n) case_docs.append(pa) + for a in an: if a['annotation_id'] not in ann_docs: ann_docs[a['annotation_id']] = a + for f in fi: - self.upsert_file_into_dict(file_docs, f) + upsert_file_into_dict(file_docs, f) + pbar.update(pbar.currval+1) pbar.finish() return case_docs, file_docs.values(), ann_docs.values() diff --git a/esbuild/graph/common/cache.py b/esbuild/graph/common/cache.py index 070ac701..60c7d76f 100644 --- a/esbuild/graph/common/cache.py +++ b/esbuild/graph/common/cache.py @@ -162,7 +162,6 @@ def get_cases(self): def get_projects(self): """Proxy to get cached projects""" - print self.projects return self.projects def get_experimental_strategies(self): @@ -183,6 +182,8 @@ def get_data_categories(self): def get_edge(self, src, dst): """Returns any information stored about the edge between two nodes""" + src, dst = self.get_node_in_graph(src), self.get_node_in_graph(dst) + return self.graph[src][dst] def get_suppressed_children(self, redacted): @@ -224,12 +225,14 @@ def suppressed_nodes(self): """ redactions = [ - a for a in self.nodes_labeled('annotation') - if a.classification == "Redaction" and - a.category not in self.caching_options.redacted_but_not_suppressed + annotation for annotation in self.nodes_labeled('annotation') + if annotation.classification == "Redaction" and + annotation.category not in + self.caching_options.redacted_but_not_suppressed ] to_suppress = [] + for redaction in redactions: redacted_list = self.graph.neighbors(redaction) @@ -238,8 +241,8 @@ def suppressed_nodes(self): # the next annotation self.error( 'Redaction annotation no entities', - "Redaction {} has zero entities associated.".format( - redaction), + "Redaction {} has zero entities associated." + .format(redaction), tags=["annotation:{}".format(redaction)], ) continue @@ -355,7 +358,12 @@ def get_fake_node(self, node): it, otherwise create a new one and return that. """ - return self.nodes.setdefault(node.node_id, FakeNode(node)) + + existing = self.nodes.get(node.node_id) + if not existing: + existing = self.nodes.setdefault(node.node_id, FakeNode(node)) + + return existing def cache_database(self): """Load the database into memory and remember only edge labels that we @@ -363,8 +371,6 @@ def cache_database(self): """ - nodes = self.nodes - with self.psqlgraph_driver.session_scope() as session: # Meter the progress bar by nodes, because creating the # nodes will be the majority of the time @@ -372,17 +378,10 @@ def cache_database(self): pbar = util.get_pbar('Caching Database: ', node_count) for edge in self.iter_database_edges(): - pbar.update(len(nodes)) + pbar.update(len(self.nodes)) - src = nodes.get(edge.src_id) - if not src: - src = FakeNode(edge.src) - nodes[edge.src_id] = src - - dst = nodes.get(edge.dst_id) - if not dst: - dst = FakeNode(edge.dst) - nodes[edge.dst_id] = dst + src = self.get_fake_node(edge.src) + dst = self.get_fake_node(edge.dst) triple = (src.label, edge.label, dst.label) needs_differentiation = ( @@ -394,11 +393,12 @@ def cache_database(self): # centers and aliquots of the source files count # as neighbors of the dst files for center in edge.src.centers: - self.graph.add_edge(dst, FakeNode(center)) + self.graph.add_edge(dst, self.get_fake_node(center)) + for aliquot in edge.src.aliquots: - self.graph.add_edge(dst, FakeNode(aliquot)) + self.graph.add_edge(dst, self.get_fake_node(aliquot)) - if needs_differentiation and edge._props: + elif needs_differentiation and edge._props: self.graph.add_edge( src, dst, label=edge.label, props=edge._props) @@ -784,7 +784,9 @@ def is_node_unindexed_by_property(self, node): def neighbors(self, node): """Return the neighbors of given node""" - return self.graph.neighbors(self.get_node_in_graph(node)) + node = self.get_node_in_graph(node) + + return self.graph.neighbors(node) def walk_path(self, node, path, whole=False): """Given a list of strings, treat it as a path, and yield the end of @@ -792,6 +794,7 @@ def walk_path(self, node, path, whole=False): along the traversal. """ + node = self.get_node_in_graph(node) if path: for neighbor in self.neighbors_labeled(node, path[0]): @@ -806,6 +809,7 @@ def walk_paths(self, node, paths, whole=False): `whole` is true, return every node along each traversal. """ + node = self.get_node_in_graph(node) return { n for n in itertools.chain(*[ diff --git a/tests/test_suite_data.gv.pdf b/tests/test_suite_data.gv.pdf index 54567ec725040ec3529cdcbac9f33bf2898fbabc..f017d6422270eb7ca08e32808055417e64ac5ffb 100644 GIT binary patch delta 18085 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 delta 18119 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 Date: Thu, 20 Oct 2016 07:55:19 -0500 Subject: [PATCH 24/37] wip --- esbuild/graph/common/builder.py | 1 - esbuild/graph/common/cache.py | 291 ++++++++++++++---------------- esbuild/graph/common/fake_node.py | 6 + tests/test_suite_data.gv.pdf | Bin 46227 -> 46224 bytes 4 files changed, 146 insertions(+), 152 deletions(-) diff --git a/esbuild/graph/common/builder.py b/esbuild/graph/common/builder.py index 8aeb8292..d1a59756 100644 --- a/esbuild/graph/common/builder.py +++ b/esbuild/graph/common/builder.py @@ -124,7 +124,6 @@ def build_index(builder_class, psqlgraph_driver_args, cases=None, # ) # cache.cache_database() # builder = builder_class(cache) - # return builder.denormalize_all() # Create managed cache diff --git a/esbuild/graph/common/cache.py b/esbuild/graph/common/cache.py index 60c7d76f..8b8c61af 100644 --- a/esbuild/graph/common/cache.py +++ b/esbuild/graph/common/cache.py @@ -142,6 +142,117 @@ def __init__(self, caching_options, psqlgraph_driver_args=None, # ``self._cache_existing_data_types()`` self.existing_data_types = {} + ################################################################### + # Path functions + ################################################################### + + def nodes_labeled(self, labels): + """Returns an iterator over the edges in the graph with label `label` + + """ + + labels = tuple(labels) if hasattr(labels, '__iter__') else (labels,) + for node, _ in self.graph.nodes_iter(data=True): + if node.label in labels: + yield node + + def neighbors_labeled(self, *args, **kwargs): + """Proxy for self._neighbors_labeled which was original written as a + generator to return a list instead + + """ + + return list(self._neighbors_labeled(*args, **kwargs)) + + def _neighbors_labeled(self, node, labels, expected=None): + + """For a given node, return an iterator with generates neighbors to + that node that are in a list of labels. `label` can be either a + string or list of strings. + + :param is_expected: Int count of expected elements + + """ + + labels = tuple(labels) if hasattr(labels, '__iter__') else (labels,) + node = self.get_node_in_graph(node) + + if node in self.popular_nodes: + if labels not in self.popular_nodes[node]: + neighbors = self._cache_popular_neighbor( + node, self.graph.neighbors(node), labels) + else: + neighbors = self.popular_nodes[node][labels] + + else: + temp = self.graph.neighbors(node) + if len(temp) > 200: + neighbors = self._cache_popular_neighbor(node, temp, labels) + else: + neighbors = {n for n in temp if n.label in labels} + + count = 0 + for neighbor in neighbors: + count += 1 + yield neighbor + + if expected is not None and count != expected: + self.warning( + "{}: unexpected no. of '{}' neighbors".format(node, labels), + '{}: {} != {} (expected)'.format(node, count, expected), + tags=["{}:{}".format(node.label, node.node_id)]) + + def neighbors(self, node): + """Return the neighbors of given node""" + + node = self.get_node_in_graph(node) + + return self.graph.neighbors(node) + + def walk_path(self, node, path, whole=False): + """Given a list of strings, treat it as a path, and yield the end of + possible traversals. If `whole` is true, return every node + along the traversal. + + """ + node = self.get_node_in_graph(node) + + if path: + for neighbor in self.neighbors_labeled(node, path[0]): + if whole or (len(path) == 1 and path[0] == neighbor.label): + yield neighbor + + for node in self.walk_path(neighbor, path[1:], whole): + yield node + + def walk_paths(self, node, paths, whole=False): + """Given a list of paths, yield the result of walking each path. If + `whole` is true, return every node along each traversal. + + """ + node = self.get_node_in_graph(node) + + return { + n for n in itertools.chain(*[ + self.walk_path(node, path, whole=whole) + for path in paths if path + ]) + } + + ################################################################### + # Proxy Methods + ################################################################### + + def get_relevant_nodes(self, node): + """Return the nodes relevant to this one""" + + return self.relevant_nodes.get(node, []) + + def get_entity_case(self, node): + """Return the case associated with this node""" + + return self.entity_cases.get(node, None) + @staticmethod def warning(*args, **kwargs): """Log a warning to logger and statsd""" @@ -186,7 +297,19 @@ def get_edge(self, src, dst): return self.graph[src][dst] - def get_suppressed_children(self, redacted): + def get_node_in_graph(self, node_or_node_id): + """Given a node or a node_id, return the corresponding node that is in + the NetworkX graph + + """ + + return self.nodes[to_node_id(node_or_node_id)] + + ################################################################### + # Setup Methods + ################################################################### + + def _get_suppressed_children(self, redacted): """Get the children of a redacted node""" to_suppress = [] @@ -210,16 +333,7 @@ def get_suppressed_children(self, redacted): return to_suppress - def get_node_in_graph(self, node_or_node_id): - """Given a node or a node_id, return the corresponding node that is in - the NetworkX graph - - """ - - return self.nodes[to_node_id(node_or_node_id)] - - def suppressed_nodes(self): - + def _suppressed_nodes(self): """ Find all nodes that need to be suppressed due to redactions. """ @@ -259,7 +373,7 @@ def suppressed_nodes(self): ) for redacted in redacted_list: - to_suppress += self.get_suppressed_children(redacted) + to_suppress += self._get_suppressed_children(redacted) # returning the redaction annotations themselves here might # seem weird, but including the redaction annotations @@ -270,18 +384,18 @@ def suppressed_nodes(self): return to_suppress - def is_unindexed_case(self, node): + def _is_unindexed_case(self, node): return ( node.label == 'case' and not list(self.neighbors_labeled(node, 'project', 1)) ) - def is_node_indexed(self, node): + def _is_node_indexed(self, node): """Returns false if the node is not supposed to be indexed. """ - if self.is_unindexed_case(node): + if self._is_unindexed_case(node): logger.info('Node not indexed (case not indexed): %s', node) return False @@ -302,12 +416,12 @@ def is_node_indexed(self, node): return True - def remove_unindexed_nodes_from_graph(self): + def _remove_unindexed_nodes_from_graph(self): logger.info('Selecting entities to be removed from cache...') removed_nodes = [ node for node in self.graph.nodes() - if not self.is_node_indexed(node) + if not self._is_node_indexed(node) ] logger.info("Removing %s nodes from cache", len(removed_nodes)) @@ -316,14 +430,14 @@ def remove_unindexed_nodes_from_graph(self): self.nodes.pop(node.node_id, None) logger.info("Finding and removing suppressed nodes") - suppressed = self.suppressed_nodes() + suppressed = self._suppressed_nodes() logger.info("Removing %s suppressed nodes", len(suppressed)) self.graph.remove_nodes_from(suppressed) for node in suppressed: self.nodes.pop(node.node_id, None) - def iter_database_edges(self): + def _iter_database_edges(self): """Returns an iterable of edges to load from the database. Eagerly (with join) loads the source and destination of the edge. @@ -340,20 +454,7 @@ def iter_database_edges(self): ]) - def count_database_edges(self): - """Returns an iterable of edges to load from the database. - - Eagerly (with join) loads the source and destination of the edge. - - """ - - return sum([ - self.psqlgraph_driver.edges(subclass).count() - for subclass in Edge.__subclasses__() - if not is_case_cache_edge(subclass) - ]) - - def get_fake_node(self, node): + def _get_fake_node(self, node): """If we've seen this node before, then return the FakeNode version of it, otherwise create a new one and return that. @@ -377,11 +478,11 @@ def cache_database(self): node_count = self.psqlgraph_driver.nodes().count() pbar = util.get_pbar('Caching Database: ', node_count) - for edge in self.iter_database_edges(): + for edge in self._iter_database_edges(): pbar.update(len(self.nodes)) - src = self.get_fake_node(edge.src) - dst = self.get_fake_node(edge.dst) + src = self._get_fake_node(edge.src) + dst = self._get_fake_node(edge.dst) triple = (src.label, edge.label, dst.label) needs_differentiation = ( @@ -393,10 +494,10 @@ def cache_database(self): # centers and aliquots of the source files count # as neighbors of the dst files for center in edge.src.centers: - self.graph.add_edge(dst, self.get_fake_node(center)) + self.graph.add_edge(dst, self._get_fake_node(center)) for aliquot in edge.src.aliquots: - self.graph.add_edge(dst, self.get_fake_node(aliquot)) + self.graph.add_edge(dst, self._get_fake_node(aliquot)) elif needs_differentiation and edge._props: self.graph.add_edge( @@ -416,7 +517,7 @@ def cache_database(self): # Prune graph logger.info('Cached {} nodes'.format(self.graph.number_of_nodes())) - self.remove_unindexed_nodes_from_graph() + self._remove_unindexed_nodes_from_graph() # Aggressively cache relationships, nodes by type, traversals, etc. self._cache_all() @@ -495,16 +596,6 @@ def _cache_entity_cases(self): pbar.update(pbar.currval+1) pbar.finish() - def get_relevant_nodes(self, node): - """Return the nodes relevant to this one""" - - return self.relevant_nodes.get(node, []) - - def get_entity_case(self, node): - """Return the case associated with this node""" - - return self.entity_cases.get(node, None) - def _cache_relevant_nodes(self): """The file documents will need to be pruned to only the nodes that are relevant to the file. Here we cache all of the nodes @@ -610,66 +701,6 @@ def _cache_existing_data_types(self): ] for data_type in self.psqlgraph_driver.nodes(md.DataType) } - ################################################################### - # Graph functions - ################################################################### - - def nodes_labeled(self, labels): - """Returns an iterator over the edges in the graph with label `label` - - """ - - labels = tuple(labels) if hasattr(labels, '__iter__') else (labels,) - for node, _ in self.graph.nodes_iter(data=True): - if node.label in labels: - yield node - - def neighbors_labeled(self, *args, **kwargs): - """Proxy for self._neighbors_labeled which was original written as a - generator to return a list instead - - """ - - return list(self._neighbors_labeled(*args, **kwargs)) - - def _neighbors_labeled(self, node, labels, expected=None): - - """For a given node, return an iterator with generates neighbors to - that node that are in a list of labels. `label` can be either a - string or list of strings. - - :param is_expected: Int count of expected elements - - """ - - labels = tuple(labels) if hasattr(labels, '__iter__') else (labels,) - node = self.get_node_in_graph(node) - - if node in self.popular_nodes: - if labels not in self.popular_nodes[node]: - neighbors = self._cache_popular_neighbor( - node, self.graph.neighbors(node), labels) - else: - neighbors = self.popular_nodes[node][labels] - - else: - temp = self.graph.neighbors(node) - if len(temp) > 200: - neighbors = self._cache_popular_neighbor(node, temp, labels) - else: - neighbors = {n for n in temp if n.label in labels} - - count = 0 - for neighbor in neighbors: - count += 1 - yield neighbor - - if expected is not None and count != expected: - self.warning( - "{}: unexpected no. of '{}' neighbors".format(node, labels), - '{}: {} != {} (expected)'.format(node, count, expected), - tags=["{}:{}".format(node.label, node.node_id)]) - @staticmethod def is_harmonized_file(node): return ( @@ -777,48 +808,6 @@ def is_node_unindexed_by_property(self, node): return False - ################################################################### - # Path functions - ################################################################### - - def neighbors(self, node): - """Return the neighbors of given node""" - - node = self.get_node_in_graph(node) - - return self.graph.neighbors(node) - - def walk_path(self, node, path, whole=False): - """Given a list of strings, treat it as a path, and yield the end of - possible traversals. If `whole` is true, return every node - along the traversal. - - """ - node = self.get_node_in_graph(node) - - if path: - for neighbor in self.neighbors_labeled(node, path[0]): - if whole or (len(path) == 1 and path[0] == neighbor.label): - yield neighbor - - for node in self.walk_path(neighbor, path[1:], whole): - yield node - - def walk_paths(self, node, paths, whole=False): - """Given a list of paths, yield the result of walking each path. If - `whole` is true, return every node along each traversal. - - """ - node = self.get_node_in_graph(node) - - return { - n for n in itertools.chain(*[ - self.walk_path(node, path, whole=whole) - for path in paths if path - ]) - } - - class CacheManager(BaseManager): pass diff --git a/esbuild/graph/common/fake_node.py b/esbuild/graph/common/fake_node.py index d0083eb4..02b666e8 100644 --- a/esbuild/graph/common/fake_node.py +++ b/esbuild/graph/common/fake_node.py @@ -44,3 +44,9 @@ def __repr__(self): def __getitem__(self, key): return self.props[key] + + def __eq__(self, other): + return bool(self.node_id == other.node_id) + + def __ne__(self, other): + return bool(self.node_id != other.node_id) diff --git a/tests/test_suite_data.gv.pdf b/tests/test_suite_data.gv.pdf index f017d6422270eb7ca08e32808055417e64ac5ffb..be4f6cdf0cc972b9beaff757053b13f6fd801ca6 100644 GIT binary patch delta 16245 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 delta 16248 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 Date: Thu, 20 Oct 2016 09:51:31 -0500 Subject: [PATCH 25/37] memory graph index works --- esbuild/graph/common/builder.py | 89 ++++++++++++----------------- esbuild/graph/common/util.py | 26 +++++++++ tests/test_graph_active_builder.py | 2 +- tests/test_suite_data.gv.pdf | Bin 46224 -> 46229 bytes 4 files changed, 64 insertions(+), 53 deletions(-) diff --git a/esbuild/graph/common/builder.py b/esbuild/graph/common/builder.py index d1a59756..a938be8b 100644 --- a/esbuild/graph/common/builder.py +++ b/esbuild/graph/common/builder.py @@ -25,6 +25,10 @@ util, ) +from esbuild.graph.common.index import ( + MemoryGraphIndex, +) + from esbuild.graph.common.cache import ( CachingOptions, CachedGraph, @@ -40,32 +44,6 @@ log.setLevel(level=logging.INFO) -def upsert_file_into_dict(files, file_doc): - """Merge this file document into all other relevant file documents (or - just add it if none exist) - - TODO: make this more descriptive - - """ - - did = file_doc['file_id'] - - if did not in files: - files[did] = file_doc - return - - for case in file_doc['cases']: - case_id = case['case_id'] - - existing_ids = { - case['case_id'] - for case in files[did]['cases'] - } - - if case_id not in existing_ids: - files[did]['cases'] += file_doc['cases'] - - def build_worker(builder, case_in_q, result_q): """TODO: docstring @@ -117,14 +95,14 @@ def build_index(builder_class, psqlgraph_driver_args, cases=None, """ - # caching_options = builder_class.get_caching_options() - # cache = CachedGraph( - # caching_options=caching_options, - # psqlgraph_driver_args=psqlgraph_driver_args, - # ) - # cache.cache_database() - # builder = builder_class(cache) - # return builder.denormalize_all() + caching_options = builder_class.get_caching_options() + cache = CachedGraph( + caching_options=caching_options, + psqlgraph_driver_args=psqlgraph_driver_args, + ) + cache.cache_database() + builder = builder_class(cache) + return builder.denormalize_all() # Create managed cache caching_options = builder_class.get_caching_options() @@ -137,7 +115,7 @@ def build_index(builder_class, psqlgraph_driver_args, cases=None, ) cache.cache_database() - case_docs, ann_docs, file_docs = [], {}, {} + index = MemoryGraphIndex() # Map work to worker processes cases = cases or cache.get_cases() @@ -147,23 +125,18 @@ def build_index(builder_class, psqlgraph_driver_args, cases=None, pbar = util.get_pbar('Denormalizing cases ', len(cases)) # Collect results - while len(case_docs) < len(cases): + while index.case_doc_count() < len(cases): result = result_q.get() if isinstance(result, Exception): raise result - case_doc, files, annotations = result - case_docs.append(case_doc) - - # Collect annotation docs - for annotation in annotations: - if annotation['annotation_id'] not in ann_docs: - ann_docs[annotation['annotation_id']] = annotation + case_doc, file_docs, annotation_docs = result - # Collect file docs - for file_ in files: - upsert_file_into_dict(file_docs, file_) + # Collect docs + index.add_case_doc(case_doc) + map(index.add_annotation_doc, annotation_docs) + map(index.add_file_doc, file_docs) pbar.update(pbar.currval+1) pbar.finish() @@ -171,9 +144,12 @@ def build_index(builder_class, psqlgraph_driver_args, cases=None, for process in pool: process.join() - projects = builders[0].denormalize_projects() + # Create project docs serially + project_docs = builders[0].denormalize_projects() + map(index.add_project_doc, project_docs) + - return case_docs, file_docs.values(), ann_docs.values(), projects + return index class GraphIndexBuilder(object): @@ -1335,7 +1311,7 @@ def denormalize_cases(self, cases=None): ann_docs[a['annotation_id']] = a for f in fi: - upsert_file_into_dict(file_docs, f) + util.upsert_file_into_dict(file_docs, f) pbar.update(pbar.currval+1) pbar.finish() @@ -1406,9 +1382,18 @@ def denormalize_all(self): project documents """ - cases, files, annotations = self.denormalize_cases() - projects = self.denormalize_projects() - return cases, files, annotations, projects + + index = MemoryGraphIndex() + + case_docs, file_docs, annotation_docs = self.denormalize_cases() + project_docs = self.denormalize_projects() + + map(index.add_case_doc, case_docs) + map(index.add_file_doc, file_docs) + map(index.add_annotation_doc, annotation_docs) + map(index.add_project_doc, project_docs) + + return index ################################################################### # Validation functions diff --git a/esbuild/graph/common/util.py b/esbuild/graph/common/util.py index 44cb23f9..d05553d9 100644 --- a/esbuild/graph/common/util.py +++ b/esbuild/graph/common/util.py @@ -17,6 +17,32 @@ ) +def upsert_file_into_dict(files, file_doc): + """Merge this file document into all other relevant file documents (or + just add it if none exist) + + TODO: make this more descriptive + + """ + + did = file_doc['file_id'] + + if did not in files: + files[did] = file_doc + return + + for case in file_doc['cases']: + case_id = case['case_id'] + + existing_ids = { + case['case_id'] + for case in files[did]['cases'] + } + + if case_id not in existing_ids: + files[did]['cases'] += file_doc['cases'] + + def get_file_to_case_paths(cls, file_to_case_paths): """Given a node, return the paths the lead monotonically up to case""" diff --git a/tests/test_graph_active_builder.py b/tests/test_graph_active_builder.py index a1f08331..a942a47f 100644 --- a/tests/test_graph_active_builder.py +++ b/tests/test_graph_active_builder.py @@ -55,7 +55,7 @@ def cached_graph(psqlgraph_args): @pytest.fixture(scope='module') def index(psqlgraph_args): doc_types = build_index(ActiveGraphIndexBuilder, psqlgraph_args) - return Index._make(doc_types) + return Index._make(map(list, doc_types)) @pytest.fixture(scope='module') diff --git a/tests/test_suite_data.gv.pdf b/tests/test_suite_data.gv.pdf index be4f6cdf0cc972b9beaff757053b13f6fd801ca6..fe8ca8ecb23c35085ff619005cadcd93d0f3f728 100644 GIT binary patch delta 14095 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 PaB_3PQ&LJONW%XgDxriJ From dcb266f9652ee208856c0595d2e3afb31ea09089 Mon Sep 17 00:00:00 2001 From: Joshua Miller Date: Thu, 20 Oct 2016 12:00:04 -0500 Subject: [PATCH 26/37] DiskGraphIndex works --- esbuild/graph/common/builder.py | 28 +++++++++++++++++++--------- tests/test_graph_active_builder.py | 7 ++++++- tests/test_suite_data.gv.pdf | Bin 46229 -> 46223 bytes 3 files changed, 25 insertions(+), 10 deletions(-) diff --git a/esbuild/graph/common/builder.py b/esbuild/graph/common/builder.py index a938be8b..a5895593 100644 --- a/esbuild/graph/common/builder.py +++ b/esbuild/graph/common/builder.py @@ -27,6 +27,7 @@ from esbuild.graph.common.index import ( MemoryGraphIndex, + DiskGraphIndex, ) from esbuild.graph.common.cache import ( @@ -95,13 +96,15 @@ def build_index(builder_class, psqlgraph_driver_args, cases=None, """ + disk_index = DiskGraphIndex('~/indexes') + caching_options = builder_class.get_caching_options() cache = CachedGraph( caching_options=caching_options, psqlgraph_driver_args=psqlgraph_driver_args, ) cache.cache_database() - builder = builder_class(cache) + builder = builder_class(cache, disk_index) return builder.denormalize_all() # Create managed cache @@ -126,6 +129,11 @@ def build_index(builder_class, psqlgraph_driver_args, cases=None, # Collect results while index.case_doc_count() < len(cases): + try: + if result_q.qsize() > 20: + log.warning("Primary thread overworked! %d", result_q.qsize()) + except NotImplementedError: + pass # on Mac OSX because of broken sem_getvalue() result = result_q.get() if isinstance(result, Exception): @@ -323,11 +331,15 @@ class GraphIndexBuilder(object): 'file_labels', ] - def __init__(self, cached_graph): + def __init__(self, cached_graph, index): """Walks the graph to produce elasticsearch json documents. + :param cached_graph: Instance of CachedGraph (post .cached_database()) + :param index: Instance of GraphIndex + """ + self.index = index self.cache = cached_graph # verify required attributes are set @@ -1383,17 +1395,15 @@ def denormalize_all(self): """ - index = MemoryGraphIndex() - case_docs, file_docs, annotation_docs = self.denormalize_cases() project_docs = self.denormalize_projects() - map(index.add_case_doc, case_docs) - map(index.add_file_doc, file_docs) - map(index.add_annotation_doc, annotation_docs) - map(index.add_project_doc, project_docs) + map(self.index.add_case_doc, case_docs) + map(self.index.add_file_doc, file_docs) + map(self.index.add_annotation_doc, annotation_docs) + map(self.index.add_project_doc, project_docs) - return index + return self.index ################################################################### # Validation functions diff --git a/tests/test_graph_active_builder.py b/tests/test_graph_active_builder.py index a942a47f..7982434d 100644 --- a/tests/test_graph_active_builder.py +++ b/tests/test_graph_active_builder.py @@ -29,6 +29,10 @@ CachedGraph, ) +from esbuild.graph.common.index import ( + DiskGraphIndex, +) + from esbuild.graph.common.builder import ( build_index, ) @@ -60,7 +64,8 @@ def index(psqlgraph_args): @pytest.fixture(scope='module') def builder(cached_graph): - return ActiveGraphIndexBuilder(cached_graph) + disk_index = DiskGraphIndex('~/indexes') + return ActiveGraphIndexBuilder(cached_graph, disk_index) @pytest.fixture diff --git a/tests/test_suite_data.gv.pdf b/tests/test_suite_data.gv.pdf index fe8ca8ecb23c35085ff619005cadcd93d0f3f728..a92079614450c823fff5667bc21ab48b4e825e4a 100644 GIT binary patch delta 3572 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 K*9^^#*!~6C+4gM! delta 3541 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 Date: Thu, 20 Oct 2016 12:14:18 -0500 Subject: [PATCH 27/37] wip --- esbuild/graph/common/builder.py | 1 - tests/test_graph_active_builder.py | 12 +++++++----- tests/test_suite_data.gv.pdf | Bin 46223 -> 46219 bytes 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/esbuild/graph/common/builder.py b/esbuild/graph/common/builder.py index a5895593..523cc09d 100644 --- a/esbuild/graph/common/builder.py +++ b/esbuild/graph/common/builder.py @@ -156,7 +156,6 @@ def build_index(builder_class, psqlgraph_driver_args, cases=None, project_docs = builders[0].denormalize_projects() map(index.add_project_doc, project_docs) - return index diff --git a/tests/test_graph_active_builder.py b/tests/test_graph_active_builder.py index 7982434d..eeb6f98c 100644 --- a/tests/test_graph_active_builder.py +++ b/tests/test_graph_active_builder.py @@ -56,16 +56,18 @@ def cached_graph(psqlgraph_args): return cache -@pytest.fixture(scope='module') +@pytest.yield_fixture(scope='module') def index(psqlgraph_args): - doc_types = build_index(ActiveGraphIndexBuilder, psqlgraph_args) - return Index._make(map(list, doc_types)) + disk_index = build_index(ActiveGraphIndexBuilder, psqlgraph_args) + yield Index._make(map(list, disk_index)) + disk_index.delete() -@pytest.fixture(scope='module') +@pytest.yield_fixture(scope='module') def builder(cached_graph): disk_index = DiskGraphIndex('~/indexes') - return ActiveGraphIndexBuilder(cached_graph, disk_index) + yield ActiveGraphIndexBuilder(cached_graph, disk_index) + disk_index.delete() @pytest.fixture diff --git a/tests/test_suite_data.gv.pdf b/tests/test_suite_data.gv.pdf index a92079614450c823fff5667bc21ab48b4e825e4a..b5f78a87400431ae8e637dffdbcaa35b2d04a2b9 100644 GIT binary patch delta 18129 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 Y3yMESjSmZlqR<#D8ftD%ICcd3A50=ca{vGU From 9e4c4b3e5e850b7ec038d3548d1718013a815c9a Mon Sep 17 00:00:00 2001 From: Joshua Miller Date: Thu, 20 Oct 2016 12:14:53 -0500 Subject: [PATCH 28/37] wip --- esbuild/graph/common/builder.py | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/esbuild/graph/common/builder.py b/esbuild/graph/common/builder.py index 523cc09d..8b55bc46 100644 --- a/esbuild/graph/common/builder.py +++ b/esbuild/graph/common/builder.py @@ -96,16 +96,16 @@ def build_index(builder_class, psqlgraph_driver_args, cases=None, """ - disk_index = DiskGraphIndex('~/indexes') + index = DiskGraphIndex('~/indexes') - caching_options = builder_class.get_caching_options() - cache = CachedGraph( - caching_options=caching_options, - psqlgraph_driver_args=psqlgraph_driver_args, - ) - cache.cache_database() - builder = builder_class(cache, disk_index) - return builder.denormalize_all() + # caching_options = builder_class.get_caching_options() + # cache = CachedGraph( + # caching_options=caching_options, + # psqlgraph_driver_args=psqlgraph_driver_args, + # ) + # cache.cache_database() + # builder = builder_class(cache, index) + # return builder.denormalize_all() # Create managed cache caching_options = builder_class.get_caching_options() @@ -118,8 +118,6 @@ def build_index(builder_class, psqlgraph_driver_args, cases=None, ) cache.cache_database() - index = MemoryGraphIndex() - # Map work to worker processes cases = cases or cache.get_cases() builders = [builder_class(cache) for _ in range(threads)] From 4e835042b13027f023fdc63c9b6f55f45e492a10 Mon Sep 17 00:00:00 2001 From: Joshua Miller Date: Thu, 20 Oct 2016 12:19:53 -0500 Subject: [PATCH 29/37] add esbuild.graph.common.index --- esbuild/graph/common/builder.py | 2 +- esbuild/graph/common/index.py | 292 ++++++++++++++++++++++++++++++++ tests/test_suite_data.gv.pdf | Bin 46219 -> 46230 bytes 3 files changed, 293 insertions(+), 1 deletion(-) create mode 100644 esbuild/graph/common/index.py diff --git a/esbuild/graph/common/builder.py b/esbuild/graph/common/builder.py index 8b55bc46..132163ea 100644 --- a/esbuild/graph/common/builder.py +++ b/esbuild/graph/common/builder.py @@ -120,7 +120,7 @@ def build_index(builder_class, psqlgraph_driver_args, cases=None, # Map work to worker processes cases = cases or cache.get_cases() - builders = [builder_class(cache) for _ in range(threads)] + builders = [builder_class(cache, index) for _ in range(threads)] _, result_q, pool = start_worker_pool(builders, cases) pbar = util.get_pbar('Denormalizing cases ', len(cases)) diff --git a/esbuild/graph/common/index.py b/esbuild/graph/common/index.py new file mode 100644 index 00000000..c1c56421 --- /dev/null +++ b/esbuild/graph/common/index.py @@ -0,0 +1,292 @@ +# -*- coding: utf-8 -*- +""" +esbuild.graph.common.index +---------------------------------- + +Defines :class:`GraphIndex` represents a GDC Data Portal index + +""" + +import abc +import cdisutils +import json +import logging +import os +import shutil +import time + + +logger = cdisutils.log.get_logger(__name__) +logger.setLevel(logging.INFO) + + +def create_file(path, contents): + """Writes contents to path if file doesn't exist, else raise + AssertionError + + """ + + if os.path.exists(path): + raise AssertionError('File {} already exists'.format(path)) + + with open(path, 'w') as outfile: + outfile.write(contents) + + +def write_file(path, contents): + """Writes contents to path if file""" + + with open(path, 'w') as outfile: + outfile.write(contents) + + +def read_json_file(path): + """Writes contents to path if file doesn't exist, else raise + AssertionError + + """ + + if not os.path.exists(path): + raise AssertionError('File {} does not exist'.format(path)) + + with open(path, 'r') as infile: + return json.loads(infile.read()) + + +def read_dir_json_files(path): + """Reads all files as json from directory""" + + for (dirpath, _, filenames) in os.walk(path): + for filename in filenames: + yield read_json_file(os.path.join(dirpath, filename)) + + return # only walk the first level + + +class GraphIndex(object): + """Base class to represent a complete or in progress index""" + + __metaclass__ = abc.ABCMeta + + @abc.abstractmethod + def __iter__(self): + """Iterate over the index (for backwards compatible unpacking)""" + + raise NotImplementedError + + @abc.abstractmethod + def case_doc_count(self): + """Returns the number of existing case docs""" + + raise NotImplementedError + + @abc.abstractmethod + def add_case_doc(self, case_doc): + """Adds a case document to this index""" + + raise NotImplementedError + + @abc.abstractmethod + def add_file_doc(self, file_doc): + """Adds a file document to this index""" + + raise NotImplementedError + + @abc.abstractmethod + def add_annotation_doc(self, annotation_doc): + """Adds a annotation document to this index""" + + raise NotImplementedError + + @abc.abstractmethod + def add_project_doc(self, case_doc): + """Adds a case document to this index""" + + raise NotImplementedError + + +class MemoryGraphIndex(GraphIndex): + """Class to represent a complete or in progress index on memory""" + + def __init__(self): + """Index constructor""" + + logger.info('Creating new %s', self) + + self._case_docs = {} + self._file_docs = {} + self._annotation_docs = {} + self._project_docs = {} + + def __iter__(self): + """Iterate over the index (for backwards compatible unpacking)""" + + return iter(( + self._case_docs.itervalues(), + self._file_docs.itervalues(), + self._annotation_docs.itervalues(), + self._project_docs.itervalues(), + )) + + def add_case_doc(self, case_doc): + """Adds a case document to this index""" + + case_id = case_doc['case_id'] + self._case_docs[case_id] = case_doc + + def add_file_doc(self, file_doc): + """Adds a file document to this index""" + + file_id = file_doc['file_id'] + + if file_id not in self._file_docs: + self._file_docs[file_id] = file_doc + return + + for case_subdoc in file_doc['cases']: + case_id = case_subdoc['case_id'] + + existing_case_ids = { + case['case_id'] + for case in self._file_docs[file_id]['cases'] + } + + if case_id not in existing_case_ids: + self._file_docs[file_id]['cases'] += file_doc['cases'] + + def add_annotation_doc(self, annotation_doc): + """Adds a annotation document to this index""" + + annotation_id = annotation_doc['annotation_id'] + self._annotation_docs.setdefault(annotation_id, annotation_doc) + + def add_project_doc(self, project_doc): + """Adds a project document to this index""" + + project_id = project_doc['project_id'] + self._project_docs[project_id] = project_doc + + def case_doc_count(self): + """Returns the number of existing case docs""" + + return len(self._case_docs) + + +class DiskGraphIndex(GraphIndex): + """Class to represent a complete or in progress index on memory""" + + + def __init__(self, data_dir_base=None, delete=False): + """Index constructor""" + + logger.info('Creating new %s', self) + + rel_data_dir = '{}_{}'.format(data_dir_base, int(time.time())) + self.data_dir = os.path.abspath(os.path.expanduser(rel_data_dir)) + self.case_dir = os.path.join(self.data_dir, 'cases') + self.file_dir = os.path.join(self.data_dir, 'files') + self.annotation_dir = os.path.join(self.data_dir, 'annotations') + self.project_dir = os.path.join(self.data_dir, 'projects') + + self._seen_case_ids = set() + self._seen_file_ids = set() + + self.create_data_dir() + + def __iter__(self): + """Iterate over the index (for backwards compatible unpacking)""" + + return iter(( + read_dir_json_files(self.case_dir), + read_dir_json_files(self.file_dir), + read_dir_json_files(self.annotation_dir), + read_dir_json_files(self.project_dir), + )) + + def delete(self): + """Deletes the entire data_dir""" + + logger.info('Deleting DiskGraphIndex %s', self) + shutil.rmtree(self.data_dir) + + def create_data_dir(self): + """Create directory to build index to disk""" + + if not os.path.exists(self.data_dir): + os.makedirs(self.data_dir) + + if not os.path.exists(self.case_dir): + os.makedirs(self.case_dir) + + if not os.path.exists(self.file_dir): + os.makedirs(self.file_dir) + + if not os.path.exists(self.annotation_dir): + os.makedirs(self.annotation_dir) + + if not os.path.exists(self.project_dir): + os.makedirs(self.project_dir) + + def add_case_doc(self, case_doc): + """Adds a case document to this index""" + + case_id = case_doc['case_id'] + path = os.path.join(self.case_dir, case_id) + self._seen_case_ids.add(case_id) + + create_file(path, json.dumps(case_doc)) + + def _merge_file_doc(self, path, file_doc): + """Merges the file doc into the existing file doc""" + + existing_file_doc = read_json_file(path) + + existing_case_subdocs = { + case_doc['case_id']: case_doc + for case_doc in existing_file_doc['cases'] + } + + this_case_subdocs = { + case_doc['case_id']: case_doc + for case_doc in file_doc['cases'] + } + + all_case_subdocs = dict(existing_case_subdocs, **this_case_subdocs) + existing_file_doc['cases'] = all_case_subdocs + + write_file(path, existing_file_doc) + + def add_file_doc(self, file_doc): + """Adds a file document to this index""" + + file_id = file_doc['file_id'] + path = os.path.join(self.file_dir, file_id) + + if file_id not in self._seen_file_ids: + create_file(path, json.dumps(file_doc)) + + else: + self._merge_file_doc(path, file_doc) + + self._seen_file_ids.add(file_id) + + def add_annotation_doc(self, annotation_doc): + """Adds a annotation document to this index""" + + annotation_id = annotation_doc['annotation_id'] + path = os.path.join(self.annotation_dir, annotation_id) + + create_file(path, json.dumps(annotation_doc)) + + def add_project_doc(self, project_doc): + """Adds a project document to this index""" + + project_id = project_doc['project_id'] + path = os.path.join(self.project_dir, project_id) + + create_file(path, json.dumps(project_doc)) + + def case_doc_count(self): + """Returns the number of existing case docs""" + + return len(self._seen_case_ids) diff --git a/tests/test_suite_data.gv.pdf b/tests/test_suite_data.gv.pdf index b5f78a87400431ae8e637dffdbcaa35b2d04a2b9..8d3ebdf077b93dc1fb82787c194123b86e0be484 100644 GIT binary patch delta 18142 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 Date: Thu, 20 Oct 2016 15:56:41 -0500 Subject: [PATCH 30/37] wip --- esbuild/graph/common/builder.py | 16 ++++---- esbuild/graph/common/index.py | 69 +++++++++++++++----------------- tests/test_suite_data.gv.pdf | Bin 46230 -> 46230 bytes 3 files changed, 41 insertions(+), 44 deletions(-) diff --git a/esbuild/graph/common/builder.py b/esbuild/graph/common/builder.py index 132163ea..49e374b2 100644 --- a/esbuild/graph/common/builder.py +++ b/esbuild/graph/common/builder.py @@ -98,14 +98,14 @@ def build_index(builder_class, psqlgraph_driver_args, cases=None, index = DiskGraphIndex('~/indexes') - # caching_options = builder_class.get_caching_options() - # cache = CachedGraph( - # caching_options=caching_options, - # psqlgraph_driver_args=psqlgraph_driver_args, - # ) - # cache.cache_database() - # builder = builder_class(cache, index) - # return builder.denormalize_all() + caching_options = builder_class.get_caching_options() + cache = CachedGraph( + caching_options=caching_options, + psqlgraph_driver_args=psqlgraph_driver_args, + ) + cache.cache_database() + builder = builder_class(cache, index) + return builder.denormalize_all() # Create managed cache caching_options = builder_class.get_caching_options() diff --git a/esbuild/graph/common/index.py b/esbuild/graph/common/index.py index c1c56421..cce9d7e7 100644 --- a/esbuild/graph/common/index.py +++ b/esbuild/graph/common/index.py @@ -63,6 +63,25 @@ def read_dir_json_files(path): return # only walk the first level +def merge_file_doc(existing_file_doc, file_doc): + """Merges the file doc into the existing file doc""" + + existing_case_subdocs = { + case_doc['case_id']: case_doc + for case_doc in existing_file_doc['cases'] + } + + this_case_subdocs = { + case_doc['case_id']: case_doc + for case_doc in file_doc['cases'] + } + + all_case_subdocs = dict(existing_case_subdocs, **this_case_subdocs) + existing_file_doc['cases'] = all_case_subdocs + + return existing_file_doc + + class GraphIndex(object): """Base class to represent a complete or in progress index""" @@ -141,18 +160,10 @@ def add_file_doc(self, file_doc): if file_id not in self._file_docs: self._file_docs[file_id] = file_doc - return - for case_subdoc in file_doc['cases']: - case_id = case_subdoc['case_id'] - - existing_case_ids = { - case['case_id'] - for case in self._file_docs[file_id]['cases'] - } - - if case_id not in existing_case_ids: - self._file_docs[file_id]['cases'] += file_doc['cases'] + else: + self._file_docs[file_id] = merge_file_doc( + self._file_docs[file_id], file_doc) def add_annotation_doc(self, annotation_doc): """Adds a annotation document to this index""" @@ -176,11 +187,9 @@ class DiskGraphIndex(GraphIndex): """Class to represent a complete or in progress index on memory""" - def __init__(self, data_dir_base=None, delete=False): + def __init__(self, data_dir_base=None): """Index constructor""" - logger.info('Creating new %s', self) - rel_data_dir = '{}_{}'.format(data_dir_base, int(time.time())) self.data_dir = os.path.abspath(os.path.expanduser(rel_data_dir)) self.case_dir = os.path.join(self.data_dir, 'cases') @@ -191,8 +200,14 @@ def __init__(self, data_dir_base=None, delete=False): self._seen_case_ids = set() self._seen_file_ids = set() + logger.info('Creating new %s', self) + self.create_data_dir() + def __repr__(self): + return "<{}('{}')>".format(self.__class__.__name__, self.data_dir) + + def __iter__(self): """Iterate over the index (for backwards compatible unpacking)""" @@ -206,7 +221,7 @@ def __iter__(self): def delete(self): """Deletes the entire data_dir""" - logger.info('Deleting DiskGraphIndex %s', self) + logger.info('Deleting %s', self) shutil.rmtree(self.data_dir) def create_data_dir(self): @@ -236,26 +251,6 @@ def add_case_doc(self, case_doc): create_file(path, json.dumps(case_doc)) - def _merge_file_doc(self, path, file_doc): - """Merges the file doc into the existing file doc""" - - existing_file_doc = read_json_file(path) - - existing_case_subdocs = { - case_doc['case_id']: case_doc - for case_doc in existing_file_doc['cases'] - } - - this_case_subdocs = { - case_doc['case_id']: case_doc - for case_doc in file_doc['cases'] - } - - all_case_subdocs = dict(existing_case_subdocs, **this_case_subdocs) - existing_file_doc['cases'] = all_case_subdocs - - write_file(path, existing_file_doc) - def add_file_doc(self, file_doc): """Adds a file document to this index""" @@ -266,7 +261,9 @@ def add_file_doc(self, file_doc): create_file(path, json.dumps(file_doc)) else: - self._merge_file_doc(path, file_doc) + existing_file_doc = read_json_file(path) + updated_file_doc = merge_file_doc(existing_file_doc, file_doc) + write_file(path, json.dumps(updated_file_doc)) self._seen_file_ids.add(file_id) diff --git a/tests/test_suite_data.gv.pdf b/tests/test_suite_data.gv.pdf index 8d3ebdf077b93dc1fb82787c194123b86e0be484..eadb8018acc8803416178730d55187c3b3c46777 100644 GIT binary patch delta 18041 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 oETnF!}{$?#6; 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 delta 18041 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 Date: Fri, 21 Oct 2016 09:42:27 -0500 Subject: [PATCH 31/37] wip --- esbuild/graph/active/builder.py | 20 ++++---- esbuild/graph/common/builder.py | 73 +++++++++++++++++------------- esbuild/graph/common/cache.py | 78 ++++++++++++++------------------ esbuild/graph/common/index.py | 3 +- tests/test_suite_data.gv.pdf | Bin 46230 -> 46220 bytes 5 files changed, 89 insertions(+), 85 deletions(-) diff --git a/esbuild/graph/active/builder.py b/esbuild/graph/active/builder.py index 7874e239..b8039739 100644 --- a/esbuild/graph/active/builder.py +++ b/esbuild/graph/active/builder.py @@ -214,7 +214,7 @@ def get_parent_with_category(self, node, category): if l['dst_type']._dictionary['category'] == category ] - return self.cache.neighbors_labeled(node, labels) + return self.cache.neighbors_labeled(node.node_id, labels) def get_child_with_category(self, node, category): """returns iterable of neighors from inbound edges with category""" @@ -224,7 +224,7 @@ def get_child_with_category(self, node, category): if l['src_type']._dictionary['category'] == category ] - return self.cache.neighbors_labeled(node, labels) + return self.cache.neighbors_labeled(node.node_id, labels) def add_file_analysis(self, node, doc): """Add the 'analysis' that produced the current file""" @@ -315,7 +315,8 @@ def get_read_group_qc_docs(self, read_group): """Returns a list of documents for Read Group QCs""" read_group_qc_docs = [] - rg_qcs = self.cache.neighbors_labeled(read_group, 'read_group_qc') + rg_qcs = self.cache.neighbors_labeled( + read_group.node_id, 'read_group_qc') for read_group_qc in rg_qcs: read_group_qc_docs.append(self._get_base_doc(read_group_qc)) @@ -329,7 +330,7 @@ def get_file_read_groups(self, node): """ paths = self.file_to_read_group_paths.get(node.label, []) - return set(self.cache.walk_paths(node, paths)) + return set(self.cache.walk_paths(node.node_id, paths)) def get_analysis_read_groups(self, node): """Given a analysis node, traverse up the tree to read_groups: @@ -356,7 +357,7 @@ def get_simple_file_doc(self, node): doc['data_format'] = self.get_data_format(node) - for dst in self.cache.neighbors_labeled(node, 'data_subtype'): + for dst in self.cache.neighbors_labeled(node.node_id, 'data_subtype'): doc['data_type'] = dst['name'] return doc @@ -372,7 +373,8 @@ def get_file_associated_entities(self, node): entity for rg in self.get_file_read_groups(node) for entity in - self.cache.neighbors_labeled(rg, self.possible_associated_entites) + self.cache.neighbors_labeled( + rg.node_id, self.possible_associated_entites) ] # Add entities with one step through a data_file @@ -380,7 +382,8 @@ def get_file_associated_entities(self, node): entity for parent in self.get_parent_with_category(node, 'data_file') for entity in - self.cache.neighbors_labeled(parent, self.possible_associated_entites) + self.cache.neighbors_labeled( + parent.node_id, self.possible_associated_entites) ] # Copy number paths @@ -389,7 +392,8 @@ def get_file_associated_entities(self, node): list_product([['aliquot']], self.aliquot_to_copy_number_paths) ] entities += [ - entity for entity in self.cache.walk_paths(node, cnv_paths) + entity for entity in self.cache.walk_paths( + node.node_id, cnv_paths) ] return list(set(entities)) diff --git a/esbuild/graph/common/builder.py b/esbuild/graph/common/builder.py index 49e374b2..a0c3df4b 100644 --- a/esbuild/graph/common/builder.py +++ b/esbuild/graph/common/builder.py @@ -98,14 +98,14 @@ def build_index(builder_class, psqlgraph_driver_args, cases=None, index = DiskGraphIndex('~/indexes') - caching_options = builder_class.get_caching_options() - cache = CachedGraph( - caching_options=caching_options, - psqlgraph_driver_args=psqlgraph_driver_args, - ) - cache.cache_database() - builder = builder_class(cache, index) - return builder.denormalize_all() + # caching_options = builder_class.get_caching_options() + # cache = CachedGraph( + # caching_options=caching_options, + # psqlgraph_driver_args=psqlgraph_driver_args, + # ) + # cache.cache_database() + # builder = builder_class(cache, index) + # return builder.denormalize_all() # Create managed cache caching_options = builder_class.get_caching_options() @@ -417,7 +417,7 @@ def create_tree(self, node, mapping, tree): return {} submap = mapping[node.label] - for child in self.cache.neighbors(node): + for child in self.cache.neighbors(node.node_id): if child.label not in submap: continue tree[child] = {} @@ -518,7 +518,7 @@ def remove_hidden_nodes(self, nodes): def get_case_files(self, node): """Return a list of file nodes by walking out from case""" - files = self.cache.walk_paths(node, self.case_to_file_paths) + files = self.cache.walk_paths(node.node_id, self.case_to_file_paths) files = self.remove_index_files(files) files = self.remove_hidden_nodes(files) @@ -809,7 +809,8 @@ def get_data_format(self, node): else: # get data_format from edge to DataFormat - formats = list(self.cache.neighbors_labeled(node, 'data_format')) + formats = list(self.cache.neighbors_labeled( + node.node_id, 'data_format')) # Get the first format if formats: @@ -867,7 +868,10 @@ def add_file_neighbors(self, node, doc): n for n in dict(self.ftree_mapping['file']).keys() if n not in ['archive', 'portion', 'file'] ] - for neighbor in set(self.cache.neighbors_labeled(node, auto_neighbors)): + neighbors = set(self.cache.neighbors_labeled( + node.node_id, auto_neighbors)) + + for neighbor in neighbors: corr, label = self.ftree_mapping['file'][neighbor.label]['corr'] if neighbor.label in self.flatten: base = neighbor[self.flatten[neighbor.label]] @@ -900,8 +904,9 @@ def is_index_file(self, node): def get_file_index_files(self, node): """Given a file, return any neighboring index files""" return [ - n for n in list(self.cache.neighbors_labeled(node, 'file')) - if self.cache.get_edge(node, n).get("label") == "related_to" + n for n in list(self.cache.neighbors_labeled(node.node_id, 'file')) + if self.cache.get_edge(node.node_id, n.node_id) + .get("label") == "related_to" and self.is_index_file(n) ] @@ -943,12 +948,15 @@ def add_related_files(self, node, doc): # Get related_files related_files = [ - n for n in list(self.cache.neighbors_labeled(node, 'file')) - if self.cache.get_edge(node, n).get("label") == "related_to" + n for n in list(self.cache.neighbors_labeled( + node.node_id, 'file')) + if self.cache.get_edge(node.node_id, n.node_id) + .get("label") == "related_to" and not self.is_index_file(n) ] - related_files += list(self.cache.neighbors_labeled(node, metadata_labels)) + related_files += list(self.cache.neighbors_labeled( + node.node_id, metadata_labels)) for related_file in related_files: rf_doc = self._get_base_doc(related_file, include_id=False) @@ -956,7 +964,7 @@ def add_related_files(self, node, doc): # Data types data_subtypes = self.cache.neighbors_labeled( - related_file, + related_file.node_id, 'data_subtype', ) @@ -984,8 +992,9 @@ def add_related_files(self, node, doc): # file.archives) and one that is `related_to` (which goes # here). For now, we don't do this for non-legacy files. if node.label == 'file': - for archive in set(self.cache.neighbors_labeled(node, 'archive')): - edge = self.cache.get_edge(node, archive) + archives = set(self.cache.neighbors_labeled(node.node_id, 'archive')) + for archive in archives: + edge = self.cache.get_edge(node.node_id, archive.node_id) if edge.get('label') != 'member_of': name = '{}.{}.0.tar.gz'.format( archive['submitter_id'], archive['revision']) @@ -1008,7 +1017,7 @@ def add_archives(self, node, doc): """ - for archive in set(self.cache.neighbors_labeled(node, 'archive')): + for archive in set(self.cache.neighbors_labeled(node.node_id, 'archive')): if 'archive' in doc: return self.warning( "Duplicate archives for {}".format(node), @@ -1018,7 +1027,8 @@ def add_archives(self, node, doc): is_skipped_legacy_edge = ( node.label == 'file' and - self.cache.get_edge(node, archive).get('label') != 'member_of' + self.cache.get_edge(node.node_id, archive) + .get('label') != 'member_of' ) if not is_skipped_legacy_edge: @@ -1059,7 +1069,7 @@ def add_cases(self, node, ptree, doc): log.warn('No ptree (case tree) for %s', node) return [] - relevant = self.cache.get_relevant_nodes(node) + relevant = self.cache.get_relevant_nodes(node.node_id) if not relevant: log.warn('No relevant cases for %s', node) return [] @@ -1086,7 +1096,7 @@ def get_node_annotation_docs(self, node): """ - annotations = self.cache.neighbors_labeled(node, 'annotation') + annotations = self.cache.neighbors_labeled(node.node_id, 'annotation') return [ self.denormalize_annotation(annotation) @@ -1103,7 +1113,8 @@ def add_annotations(self, node, relevant, doc): annotations = doc.pop('annotations', []) for relevant_node in relevant: - annotations.extend(self.get_node_annotation_docs(relevant_node)) + annotations = self.get_node_annotation_docs(relevant_node) + annotations.extend(annotations) if annotations: doc['annotations'] = annotations @@ -1131,7 +1142,7 @@ def get_file_associated_entities(self, node): """Returns a list of entities that are 'associated' with a file""" return list(self.cache.neighbors_labeled( - node, self.possible_associated_entites)) + node.node_id, self.possible_associated_entites)) def add_file_associated_entities(self, node, doc, case_id): docs = [] @@ -1139,7 +1150,7 @@ def add_file_associated_entities(self, node, doc, case_id): for entity in entities: - case = self.cache.get_entity_case(entity) + case = self.cache.get_entity_case(entity.node_id) if not case: # Skip, the cases is likely missing because it is omitted continue @@ -1171,7 +1182,7 @@ def denormalize_project(self, p): doc = self._get_base_doc(p) # Get programs - program = self.cache.neighbors_labeled(p, 'program')[0] + program = self.cache.neighbors_labeled(p.node_id, 'program')[0] log.info('Program: {}'.format(program)) doc['program'] = self._get_base_doc(program) @@ -1179,7 +1190,7 @@ def denormalize_project(self, p): self.patch_project(doc) log.info('Finding cases') - cases = list(self.cache.neighbors_labeled(p, 'case')) + cases = list(self.cache.neighbors_labeled(p.node_id, 'case')) log.info('Got {} cases'.format(len(cases))) # Get files @@ -1188,7 +1199,7 @@ def denormalize_project(self, p): case_files = {} for case in cases: case_files[case] = self.remove_index_files( - self.cache.walk_paths(case, self.case_to_file_paths)) + self.cache.walk_paths(case.node_id, self.case_to_file_paths)) files = files.union(case_files[case]) # filter files @@ -1353,7 +1364,7 @@ def denormalize_annotation(self, node): """ ann_doc = self._get_base_doc(node) - entities = self.cache.neighbors(node) + entities = self.cache.neighbors(node.node_id) if len(entities) == 0: self.error( diff --git a/esbuild/graph/common/cache.py b/esbuild/graph/common/cache.py index 8b8c61af..c14ae267 100644 --- a/esbuild/graph/common/cache.py +++ b/esbuild/graph/common/cache.py @@ -11,8 +11,9 @@ import logging import itertools import networkx as nx +import types +import cdisutils -from cdisutils.log import get_logger from collections import namedtuple from gdcdatamodel import models as md from multiprocessing.managers import BaseManager @@ -28,7 +29,7 @@ FakeNode, ) -logger = get_logger(__name__) +logger = cdisutils.log.get_logger(__name__) logger.setLevel(logging.INFO) @@ -38,23 +39,6 @@ def is_case_cache_edge(edge): return edge.label == 'relates_to' and edge.__dst_class__ == 'Case' -def to_node_id(node_or_node_id): - """Returns the node_id of a node if provided a Node, elif it's a - string, assume it's a node_id and return that - - """ - - if hasattr(node_or_node_id, 'node_id'): - return node_or_node_id.node_id - - elif isinstance(node_or_node_id, StringTypes): - return node_or_node_id.node_id - - else: - raise TypeError("Not sure how to convert {} to node_id" - .format(node_or_node_id)) - - class CachingOptions(object): """An object to hold the options required to hold the required options @@ -164,7 +148,7 @@ def neighbors_labeled(self, *args, **kwargs): return list(self._neighbors_labeled(*args, **kwargs)) - def _neighbors_labeled(self, node, labels, expected=None): + def _neighbors_labeled(self, node_id, labels, expected=None): """For a given node, return an iterator with generates neighbors to that node that are in a list of labels. `label` can be either a @@ -175,7 +159,7 @@ def _neighbors_labeled(self, node, labels, expected=None): """ labels = tuple(labels) if hasattr(labels, '__iter__') else (labels,) - node = self.get_node_in_graph(node) + node = self.get_node_in_graph(node_id) if node in self.popular_nodes: if labels not in self.popular_nodes[node]: @@ -202,39 +186,37 @@ def _neighbors_labeled(self, node, labels, expected=None): '{}: {} != {} (expected)'.format(node, count, expected), tags=["{}:{}".format(node.label, node.node_id)]) - def neighbors(self, node): + def neighbors(self, node_id): """Return the neighbors of given node""" - node = self.get_node_in_graph(node) - + node = self.get_node_in_graph(node_id) return self.graph.neighbors(node) - def walk_path(self, node, path, whole=False): + def walk_path(self, node_id, path, whole=False): """Given a list of strings, treat it as a path, and yield the end of possible traversals. If `whole` is true, return every node along the traversal. """ - node = self.get_node_in_graph(node) + node = self.get_node_in_graph(node_id) if path: - for neighbor in self.neighbors_labeled(node, path[0]): + for neighbor in self.neighbors_labeled(node.node_id, path[0]): if whole or (len(path) == 1 and path[0] == neighbor.label): yield neighbor - for node in self.walk_path(neighbor, path[1:], whole): + for node in self.walk_path(neighbor.node_id, path[1:], whole): yield node - def walk_paths(self, node, paths, whole=False): + def walk_paths(self, node_id, paths, whole=False): """Given a list of paths, yield the result of walking each path. If `whole` is true, return every node along each traversal. """ - node = self.get_node_in_graph(node) return { n for n in itertools.chain(*[ - self.walk_path(node, path, whole=whole) + self.walk_path(node_id, path, whole=whole) for path in paths if path ]) } @@ -243,14 +225,16 @@ def walk_paths(self, node, paths, whole=False): # Proxy Methods ################################################################### - def get_relevant_nodes(self, node): + def get_relevant_nodes(self, node_id): """Return the nodes relevant to this one""" + node = self.get_node_in_graph(node_id) return self.relevant_nodes.get(node, []) - def get_entity_case(self, node): + def get_entity_case(self, node_id): """Return the case associated with this node""" + node = self.get_node_in_graph(node_id) return self.entity_cases.get(node, None) @staticmethod @@ -290,20 +274,23 @@ def get_data_categories(self): return self.data_categories - def get_edge(self, src, dst): + def get_edge(self, src_id, dst_id): """Returns any information stored about the edge between two nodes""" - src, dst = self.get_node_in_graph(src), self.get_node_in_graph(dst) + src = self.get_node_in_graph(src_id) + dst = self.get_node_in_graph(dst_id) return self.graph[src][dst] - def get_node_in_graph(self, node_or_node_id): + def get_node_in_graph(self, node_id): """Given a node or a node_id, return the corresponding node that is in the NetworkX graph """ - return self.nodes[to_node_id(node_or_node_id)] + assert isinstance(node_id, types.StringTypes) + + return self.nodes[node_id] ################################################################### # Setup Methods @@ -325,7 +312,7 @@ def _get_suppressed_children(self, redacted): to_suppress.append(redacted) logger.info("Walking down towards file with paths %s", paths) - extra = self.walk_paths(redacted, paths, whole=True) + extra = self.walk_paths(redacted.node_id, paths, whole=True) logger.info("Found %s other things to suppress by walking from %s", extra, redacted) @@ -387,7 +374,7 @@ def _suppressed_nodes(self): def _is_unindexed_case(self, node): return ( node.label == 'case' - and not list(self.neighbors_labeled(node, 'project', 1)) + and not list(self.neighbors_labeled(node.node_id, 'project', 1)) ) def _is_node_indexed(self, node): @@ -580,7 +567,7 @@ def _cache_entity_cases(self): util.truncate_path(path, entity.label) for path in self.caching_options.file_to_case_paths ) - cases = self.walk_paths(entity, paths) + cases = self.walk_paths(entity.node_id, paths) if len(cases) > 1: self.warning( @@ -615,7 +602,7 @@ def _cache_relevant_nodes(self): paths = util.get_file_to_case_paths( file_, self.caching_options.file_to_case_paths) self.relevant_nodes[file_] = self.walk_paths( - file_, paths, whole=True) + file_.node_id, paths, whole=True) pbar.update(pbar.currval+1) pbar.finish() @@ -648,7 +635,8 @@ def _cache_data_categories(self): category = data_category._props['name'] self.data_categories[category] = util.remove_index_files( - set(self.walk_path(data_category, ['data_subtype', 'file'])), + set(self.walk_path( + data_category.node_id, ['data_subtype', 'file'])), self.caching_options.index_file_extensions, ) @@ -673,7 +661,7 @@ def _cache_experimental_strategies(self): for exp_strat in self.nodes_labeled('experimental_strategy'): strategy = exp_strat._props['name'] self.experimental_strategies[strategy] = set(self.walk_path( - exp_strat, ['file'])) + exp_strat.node_id, ['file'])) # New files have 'experimental_strategy' as a property for file_ in self.nodes_labeled(self.caching_options.file_labels): @@ -761,7 +749,7 @@ def is_omitted_project_or_neighbor_case(self, node): if node.label == 'project': projects = [node] elif node.label == 'case': - projects = self.neighbors_labeled(node, 'project', 1) + projects = self.neighbors_labeled(node.node_id, 'project', 1) else: return False @@ -769,7 +757,7 @@ def is_omitted_project_or_neighbor_case(self, node): program_names = [ program.name for project in projects - for program in self.neighbors_labeled(project, 'program', 1) + for program in self.neighbors_labeled(project.node_id, 'program', 1) ] # Check if project is not released diff --git a/esbuild/graph/common/index.py b/esbuild/graph/common/index.py index cce9d7e7..36e852d9 100644 --- a/esbuild/graph/common/index.py +++ b/esbuild/graph/common/index.py @@ -273,7 +273,8 @@ def add_annotation_doc(self, annotation_doc): annotation_id = annotation_doc['annotation_id'] path = os.path.join(self.annotation_dir, annotation_id) - create_file(path, json.dumps(annotation_doc)) + if not os.path.exists(path): + create_file(path, json.dumps(annotation_doc)) def add_project_doc(self, project_doc): """Adds a project document to this index""" diff --git a/tests/test_suite_data.gv.pdf b/tests/test_suite_data.gv.pdf index eadb8018acc8803416178730d55187c3b3c46777..b35d5dc4daab0505e17296a85c7c793f0017abcd 100644 GIT binary patch delta 18261 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 delta 18186 zcmV(*K;FNM=>nGN06#^D=i@$vRL?W$`F;Po2HyPoXA{fFi5RwKv>K_d>m*?y6K7V&a zxekivVN{(QMzN%9RR3ZoHqOMYuP5-%nOJVqfeMWLM(*+}ae3c*Hd9^DGN)A~iG*Y}4Pi4f?*=U!4uK4dcHZ%mD_>g35i)B9Ss!{MrZsh;ZVu z(Zn#u`vT=H!xTOgIGvpy_%buhK+hMMVIHdACx)p<_66S0LM1x_?|)`52>hmHLf|Oe z;rW>-0?%eI4m^=kE_kT(De@HbAkN{tWo_X8?DoKY*&72tY*7yH$}9J~eWp_FNI>VI zz>RR5wV7dj-oC(^Jb8jPumbM5Jk=Xm1l@Pb#y}=j2+YVn8JLz`6PQwY()dp0jy>5Y zlwti%*0=crZCPKSxqs#7fu>Fv$-Y35T)r<*TX}d*Mj2jp%fvtuhQ}NVRL!gogy4}_ zP6uXP#LeSoaRsi9%W+XI!udHLXXVYjz#DiSui<%K#WOtMEpHtj{hgd7jKQiBNTp&( z$tZ0Br~?BHkrGjurvSBv@#ytK_!j$MtFzVIVk&lb{)b||(tkO>Gx?wXd_%YQ&gdI@ z*w;T)LmH#L{@$Uw8Nu`W4&y)KkGeV!;GvpKic;(G=aB1h>EEI5-W(en$ z_s(gClpFb!8|CwGN(&VIeS2&2aKhevjdD2q)!|g-@bt>z>B`}`Umea=4)3ZQ-UWyM z6Nvwx^et)s-(9tT?mgGu+qFdMnlE)Nfo=ZKO@m9FLw}nV27`OAy@wnK4$;y13l}XV z^@1fs_ee`Rhpv@6gL~&H*Zte!d&%LsQs-WDZ`aJez4yvXI`_?$=XOajq5E&RWp&p# zo^|87XRW^FKRoLeaCv}oKhVqpvQg#M5{e=( z+JNo^d9ne0fa;I~`1pso1@;f1*U@j$L^KB-1=@N9k3(D0WK={eaWe|zU!r={g?@mZ zfh*RdRd8-M`YsaTswYODgT8w72pUFTf*kgNRDbV-yWEWK8a;}3p-<2kqq|2xMR{~R zoblG^A5a!Fnwx=^-6#V0T#hcqX=>f*X4C@DyAwTuKEU?T7Gy)UsDwJvMQABni7r9k zhGS2ox6rS#7ei6b@WH{ zSAT56&*GOxy`u+4N8#BLYC!GE@q5wt(QfoZG7|I>{7#^gcm|$LOLXn1eza!vG@Ne) zsL7}ooex*6L|4N|?nE!3SK;?tcxoKi<5~Dpya{i`FH!BZh2hxAqu0S(@&NB<_)UTL zUkh)#4ebCJK8PNJ-}C5K0C_c*s5WX7b$^OB(K0iQ9UQ%8bkFEBqrZR|VUYpg-wVHq zXdSu&Z9zA}cy2?7&~xY=n5(~_5zJu$JK!A-;P>%o6rxO20`B$-y^7vS?_m&gFY`Xz z!fq}UCn-v-K+YH+frUsUR)k5UtNA`w0HE5(MLy*z}txMHe^nF(0CZ_G&B=t z@IrK@0_&{=m*9Q&ql54}1aI{udVdNXgLnHqIt4g)2H>Dp;NS#EXTto<#(j7JUXC~5jriO6Uif__l`qL0vT(Z8mDOMm~9aWm_f ztC*iM$C%^H3Fg00kM9FW-H+}C`ltn6{5`--8CAni1HbD4hE?!Gax5ANOCd2B z@cXJsC#hf)~@-T=@dRJ1Ap{1=@cLbKtoGz zJcK$HYyfe9I>;GaLvE?FYse)*8;;SDt_6#SrcUeY>hy?We>ydUI~GX`hmh1hWK51- zPObyC9hu$-&rYY7fn*;-H|Z8ji*Fj1(Zczpwcz}|A$mdo5H+7X!;~CyNS#BDD?f66 zwR^VJb@SH_4pEWr1%FGnb`Qz(Zvvo`-T7p1!OgJOOQh@&b$x%|5WXH>j=Y5O?v+tg z1Y2bO^5BqKYL}L7T|OURj;8nRbIWc;f()UlefwOpOW8@M4m&qCi2#(t>9%wmshdRS z#!CIiZ&mt#d4$x?jYoe6b?@|ZaKYr+(s+2yq2MCrAric61Ai%&G@z}E8UTFo*Nrq97FAzCMrt=&|3;~%|umfzgRPQiS zPwm@_@pt-(zBi0IeTPBH(DN=x52H9ihh?2`HS8o(&`~8qt11=jhPUn}^A_A1+&X^o z)?jyVDNHyMQGaSUuw-k07KSsUZyA&``@|u+-*c|Hq`$ur?vo_=XQvk|;s0w0*PMHAxH1oKTcbd@_Wvaa*ZprGT>rmy5N`Y$gxQynNIi@$fUO?3sbJHXVfzraX4v{+bHLUHTQ_WR*jB>U z4A=SD^M8;8Tb|s5`4G-qiyY9d9=oT~$N7{#a!iE&W;ma;XTkYi?iQqmdm;K3)C)BS zbr$MssN?W16s6h7fK+hVa1y7e=>Hn%Q zfaWD26EcH-YXyzat{ie8Cvri{jXa>2`4G`?5m?9H{0qXah(e(0g+bSeq8PkG0wiM+ zr9ggWKnu-*%&Y;uv=;Q>`Y}zY@tZgK|LtBA=+5M?9&H3o=~KKEzevrbJ_bGI6mvE6 zOMmu|Y7SS=ea>%EYt;KRvgW_ES8HF>)#`q!@6-Rwu+Mm@aK7-GSz``cbe8W}z1Bb2 zuCsk@ff*y^=D%DbZ0U-`BZ7rNNKY0 zWoeQyQbMhzk&3^}k|2jBKzk4PEqr~Wf@^)$!yA*JxOZMvY z46WyN7KYL3X_MY!aX8$}Pxu~_%WN6O+Wq3UDi4}8a%ytdlFpA&Ypc0f#3pkQDu47d z;b+x3v!%Y^P;n}g;4nM5XpAyl@cO2oSax@<&rJKB`>I<{(idQE_d;>g`d^iIm(M&@ zerLPb^eFa$TSFK@O@ZY!o;Z{L@+^XH*F$mBkM4WbM)Z#OSiwm3NwS zo-+7Jr$)Z{PL3iHlvhFnh~nUtxPMrEq246Ks93@7Fq^1xlY6Ipdv=rM?r|F%r@iU^ z!In4hqVku68&~%D#LKRH2QR{bLl|!t`}URptNbXyYAXH?HI6dCyaZ(pYNoN91)64u z@g9JT@)jqAk5P8g$?BX%w24#k-^*&sunERRA@k@-dM`U4EE7MvO%6SZKY!DGWTjs~ zZ=;V8U5)D4qMn|}t9JQW!!Em?+F~B2`29i67WXj4?F|O9$4;FTzC4LqPqxC{JJ!n$ z$ft`sBi1M%@kWIR6V*F3bqLw0I?VZ?#Tucdbs6dqwm_lwsOm6nf`Zt{N5Q*DfrLbS?eb=dP}qJQ*qlo*OdO+ukQPi?qFYxCc{Dj1V0A5Exg4y#Tn-D%mw? zy}?RFt@Tz)H?olbU5NhYLhg5x^>^U6ykwtcp%wg?vPrL_DTcSPJb$Ni!hBQoFwPy+ z>GUp#^C^4<67l_b0FB{1Ap6+Fms-t^;-oK5p21%vlhru{1GC#qR=dL{*0ta|Q*BfV zskpjGo?3{fUpjJZ{RC&+JtK@)>DYc&eR|@gD#q(q)z6`SkgM?tUN9^$*r14hm0b)R zb6B1jF@t0G61>bpFMpPr051*PRbAgWK!#W{;f^zB~o9>ux^gbOX({o;1NwDuhK^ z1d%ybaKE6;y_XUA2&acxR%>)x)=1Z3wGO715uiY1dWDiuI)6L0s|!4?BSR+?(1P*8KU#hu-)@`3C&z{K?hsRcC(hz*pnN4}I^R#f3HM zkN3ZI_kHEp%U5Okb>%++N&{^ANB>F>vdcjt?2t?2U2{2#3){m9uE_Or%em$JdhROz zA=isxtwVG=9e;>U;gFzrIw*^d`XV8R^x_dUR;#lX;4N!qqle9IN$7b=!Dpa1~Uz(;RZhyZv_cA(k){ssV;Fme`JMFK0g6ZjC|$3VS3UsGRK z8&jqohW_tR0D#yDq9ZXBt*foizkRUv<}HPR_w`PJ+J80t-GNJHX6gd*~#i%J-k1$?q*6V4kM>?9(AWW+uKCljWz7F4UP(!mC zon{#OWq&ogPn~0a$56~Lu75nJl2yA@wCYJp12SF*pfMU0^cgrcP#QS_92uDY7bR1L zEd!K_n=?sfgYW`^wvoU^jYUh|l($JH$t2cMv&uI7S^K;<-q<;EgxNMSf&TWHtFJFV zf@fW?%yHZ3r}Q=KH6Z(6lVdk{a2;>8fj*LOuz%K&)uz>{jSjb9G_Ey!JZ=xP7#7S4 zTqFA<>iaw%%I$LBC)-4mz))XC^z4ezpOg>dwpeIOYWoYkrKS> zhOF~*;UrLiqqy0SNwUfaiex;dJT@0i%1pyNJAoHQyMR_j^+%61- zN`F+>VXudgC}56277FXDy7pQ;h8#i!kRuAXQLrc!!5Oe560C6eF(8Hn43J>PFAvwO zeYE`fUEj8Ad5WfvtW#Eb zu&3KY$r@43hIUc<$QIezscE>o;q#kJC9d&KX^~x zf79)kUyOzFaXbN=@q&>zMaPtJJs+%$nuG5hYq;pq^XoVMsQmJ)TL?Tbii3gA%a;3 zqz1w;=m}m7GQ4$=piL+s|EDe_uTw) zW;wguwcNctFLd(xsFP)kHh-nkns)_Q?XHyGxFYm8wE`t}fyWV$NY>WbR(KEbE1u0_ zh@x?O>uLd)22K(sgOrM%VNxWJqk=;&-rckNnFS3S9^U?&LqGb{w7PGFHqBqT z`NsN3r{4HOx+Ohn<-F_H&A4FqI8E#Pb>ANT$=b^X>bf>QdCj(?2fugCf>sEw6aL&h z`Z~P_=FtH5&0%@!$A8X`U0*oAa53H9^L&?kF86NsZ1&zQ-0s=oeOP!R@k-*ja6Dni z@Ghs*6%W#wX0@(}lQj6qlz9eh7;kX$yOOL^&u&2`Y$94*TDv7qV4O}>v^YYnttSbc z4meK&e*>nb@HwJG6Kn*I7K&D>1br01sU|SxjKIotG0@{Q34b1#ngGQZYze6XWa|q= zyaCA)Nao!DyRTGUI8*?DR)A^FQyt&cFshq3FI>O+dq@7VX5}@{uY5qWwCn2L<<|(( zgvGVVhhI8*m};Kr)?6EZ9W(p(-u4eVTHgK6o#hv=`c7BO7I%88$1VBiOm~A#_tzi4 zg{=xbfGx@14}Wl^ATBQAlKe1jqy-o4V$4Rf;0btwNjk|SR7JYT6jh}_DL6|r%W*S( zGqZ)iLH#ZLw+!DheoMGHaC7i(`fg^se!F42al3GL;O=0!Q{QQzI0$zlhuw}TrxP}p z3o{=2$11^N)O!qZjR+4g2JJ4&Nh4raS72Tp8>VkN`DuC4lqvJ^BXL~LH}{PEeNL^_JZt2W zsevkY4~|g=s&?eq$bU!F7yf}hdHV8o1x+NvJJQC9RWJOk-(73fsUk30z{ezTCp@k2 z+z8n8uggOGNk*d%&vX~`E$s0AJG zt7c8HbWLyd^53%f7c6Gkh%KG5+bCTo9FFi1%FoMYS06P~4sHrQ8>EA^Id#G$3{&*p z+B^^hF;m~H@SKuxvb6-7FKBkFM^1nWQ-K~)gNsC=2f_$er9{c$L^v4@MN^K%EQ};- z7JsgCre|R+>Sih0FOUX^FoiG_W+PSM7?=ThwqgXt>ckr69FGCI5D{TRikfIM6{zx? z|2UF$xl1cYp1XSd_^YXwFR{3!xaO9ZKe+6Xk;T-ro!8wy<00Aq{DdnXdvqf%Q+0s| z*SeOzb#Rkx?Y#9bbF$Q*1AnD^9+xG1b-4x{Hx$Z`egLtIMT%$TQQ7?) z@5hc0opir*nUjk1b_eTGZIpSB$Z^BCO%A~hwL5C(j9{z+EG62U@uO?y?-IS z$rll$Cau@|C97xETK5&obRpnMH*Wn$+`!HS6}hUg`q z8ho{yq$QhZ-}u(A%YVj!_jcYe>HKKtl1G15KJ?uFr(eRY9J{DJ7%JD^IP(YPN6T-6 zVSRXFa(48*wo88XJPzaJt8W3Eh#CK51K^|q^pd;enwLEIL4KGYb|3WolV|Ibu7(*E z%xAsW3xGKo)f*BPu%hV-Xb75>36tE09e)Z~?Sg{!Q3b?#H0MB)1oe^d+%Nz|@h3z< zYp|KVLav~LF;&>F1cqw$q`%zrUq>G-f7Vr9zWUP6_BB)-JAR7K->`A&dEftNtnRxWv$1k!J4ZLzB}C>qYJyzK3YVccs$IA9zHHv?{s*O6FbvZpVdIS0%5f?64TJ( zXo#^Gcw=-=C=)kkc&jDl^ZVlo9uP5+pk2;&>R!z{6rCESqQjKtVA32&Ff;*XvTBTG zzZ^Jq>QqTVwpLOR0G||267mK09DgVlR|uH!MB#FZPALwY zevCRlq5yDZ2OljT-!jz~FBc|XUXETqsmwOp=k6d`vOzbjd0qlg)Lx1v|{|Lqj zh+x^jgE1g_q_|W8CLQpH0gUJ1C-GER0@dJO>fW4Ys^)bKts%gRo&%mjqy$i34om{z z5zX{0?*c=@$}}m8M9~O0+agG5c$bGn0gG)l`ou zMFRwhK&A>{!xHXA00XcPn%$ohriGz#lCZHcs`bV*dQ&2jj+)|xd4FXH^Qt1uEA>t0 zh5iHUQk10%*4coCfs2Sa$HpXj<;SK}M4uM2tsU#1d!hUmu6j4JI6Xexv6|9MbXApi z{;2%sYabqb36B?nnT3MoX*pa>5fr)(W8zN$lBr|X@VyZ57B^n$+M^@h#qTPa*G~+T#AaG zDkvp4%|wzeLC-L}(U1y9B7U1y%~Q#$fS(tngbSR8%)zuiI!3dK;z`hsXe?(H7=>oR zECMZ`kSNjB$sci>eT8Q>P&vSHtPrTu{>qsqRvc^M6(s;naes9uwGvocadk(>>XDb$ zH;ruXgt~%jm$dWIDBpfbc{RTEZ2QdWOItxD(aG22@090UDg)*ze4n}oU_)XSeR7-t zCLJQ|%#v2mZ%j#Pr}C_3yHc0 zBb-zj-oFh_8GjHKH%yqYfx3W{BR|C1h`M-rMV?1hZL80$zPzZ8D2$`RH+}|fH(D(> zFL7Pwy1})>b-(MNOZC<3y3fv?%VDPtwB5?+dFLK$#tm=m=8-e#oa&^Vgf)1TS0;Sb z>p90)!8!mJK5$Y{fCw8^Cg+>X^6XsraXzT9M}<359e=AQIbx1{H#QxaQ@i-|zOR^J zRMm3fnRqD1($t*8(QquS@IjCbUH@SU}#3ysxMs=Ru>@ zroh4D)u`18v)}LYdo&Q6&~qN07KVf*2W|D(y}odSwehl7^x5LNxXB)OhvNZ09*NU% z1D}_52Y)>7ga9THb1>!)q$=`6abhSeQJFCy_|HEV!1DuDbJqQ`+lg8or4a|2!?6=s zPDnDKGP6Qb;EBczp1!Xp6}($#fivdy1+(6ysLi6|nx5{f@eX_(zku&t)84)Y6ujn< zQ{Iu0>fow!AfoU8AuX@!P(@Gwol!^mj+J9rs(sCzj!b&>VQdtJRbdo zeGp&=)(*N;ZvTxF_qmq3-q(I=_|*21SEVIJhs))3X`Q@_;gLlE#m=mu{KymFooZ2} z?M{crtu@7U+LXg#jw@KKlU#wgJH@Eu!MGxAr4V4n=bx8GJ_nicxf0m<{H%Zl%x*nH z;0Q8OBB)NpM{|?(j39qo@jTjABd*53zihH}W>A3!^_l{Y&0?L4ik^v5k3EzZHPNVU z&hFE%FpJLoL4gDz3WaW&SSuq9>Y` z%prfwLUUrqpV9PkM`LudO=^{9)^%-Vi$_0hqtCl#A)X70 zSaF*Zd_rT!0MHlccy*8!HKwHm!Ej)}D^BC6pI4 z*jj$=WAP%_xT}9go@cgqM_tL0PgyEH{^c{1wd1a#FJIBAj=pmL8&A>Yo7a_y&;>t4 zc{{rU;$B+N@O~?2BhCl3uNa;ap0mFa{(0nG!<)jJ_IJbYMs%-OUy1$3`hJX=#>*a$ z=ymWJBTYSlLnwrOGVIC@Nu(SS#cI6^*qH&#PRp~FUs!)eEv$u@3su^g;EQ1QRwWd% z3mWkW0y)4O_l9HON=L0<*2NFJP4!3NXh=AVM)EV0OkdX9TW8Vnj$GNV_Z4i$RCo1Tj9A zxLs{hC=7oXo5f&im~f>{(hH$CLnlK2@SX~BOvry0vPo6mNQm|F5Br|*QN{^65WwMz zNH#{oRRX7#LZO7&=L7B+@_NG%`^iXC!}G(N!b4#u9M)MZ9xh|0g1WdT5#qhRkmSXz z7@=pnR>~q4367^Uk%V9*LLikqhvTP|2oMl7;5ra^tAga&fuqFVTcLC)HvI?`xA>nKC!BRNK9Y zzWm}2bu>Ne#9jBfNB)^hsUp-MTVA=QS)+g8`mE89=#zl!kUN00a?~WP*IcFDs@J)cpc!^0V`LTzM+|ztN;3;5 z;%bd5#mqvYDFBWQLOVb`6{bX#7h->RLj0R(w8UMZ&+j=7wBu$$^KuI{)_cyk8i@ zE+*X!OJMHZI{ntGS1q29yF)Tb7sK= zg{W8Q)Twh`enn$a$N{}qQfz-tJOF>f$94!Uwajz5>k7{fv;*%n?iB7v_u~ijdyJ0>4@4e_9zcHw@RP2%8Mc6+p$ zOaf|GT}@2_`uVz=YMy^-$Ys(ltwyExR7Ko%xhhD0CHbzJnubUixHVN%ok^=3AsinW z#@z>k$c^1kf`fDuQsd`jO%OF~YM>fi#l~U$hyCKE=PTj)0k>eR6%jKKI@B2C1feaWDM24cbF>trv82Tm^x@HFcSftl z@#70T^}#kOJjn-6QOILQc5qDjOZfJJuhxBh)>VNSr^+t`whyhGHHYnuQfgD$8ugzk zQ|*861ow0_iZy?xIVOmXI@hAwGX2eE?*fjM}hH zzVOrN=_tj;x>b};x?6L1@gdDa+6VPdsb5jQnte6*p89{i-0|wq)hBbt*?g+H%Ha)I z11N7aV&nLlOntFBWz-;*mAB?2T&AU7%eORZ+qkx3OweZAs^seRiEP!LDynLjLb9gA z8S`|8+L=xnme=gN>sv`TTE z19MbFA60)v%~5P%qKIo@{Kyt|_(9dML|h8}SCJDw^qEJvZr{ zP+YN~bkVE};~j2KR#)U3?E0o~_gx#izFl6`Xpb2@wJ}$;uem)~zkYy%#VJH*;UGTx zG^}57g2i@=T=j(xt91BoJ(hTU+%^??@is{n;UIHWWz*6~Y|(O_MJBDk(=bdyAQ@CR zRn~uc#D;B<4_pZz1Mh?xsYLroCf8ZuBPEAMnF6Obs1t%Ze-wKKC<1yhihV{8V5Oqg zDX!4f0~Ux^4f7zE}#KwQ>(+kqS+_7V1c1M}2z#t1S=%x24`H2t7 z<8N}@#~(GlZF<}J2h+!Xu1?#fJx{w_ysZP0BfAu9}zmimyY*F!isYIrMXCu^yC0&V8_lHkwJt)WAa;~$QaZ|3Ho6{K{&;pAet4xL=oAFj0T)K>p>?mPL!9ZD-ULJ zQXOPD1;zR`-+yfT(rKASZ?Sd#&U^oYRWGOLJ=abWi@8j$&Tf0@{yYBC8JlIgqWgv~ zfAtFt%N7WJR0C{IvV)MN*@)hiSKfaae<=QH{AZ~TQ>RiYv@&yb=BCU&nMab3W}Zks znfZD0Smwos_mb~s-fA$=$%zR{;$^O!ayFw}~~7c*8iDP^=~kRz6$X z$e7b6T$@jGjV-a5s0}e$b4*q;6VRbjq4Nh-80a7GEj0lM2S_yel;U!N$j*Ps3WhmA zb5g>c-~}d`T4PlO+3Je%R9&hNMa4K2^~u^OZb&qK4cU|kG6Vu0XOp?W#3gWq1O*#i zaTeQDMlg64GNtNj&3SYESmqarj8d8Ac*K*}nFG_)b3#HyMPZ5xc4_Te)lJ{$8WQ8@ zKm4na$JfrkseR+kJHAKn4cdPqxTQHm(V|V~*0Ba^S#f>SnP0TkVoIcPP3o(f-D%7{ z_8VL{^Wgaj{MdCXe*2@{XMp#{M?Zm8JP(5}i)7mVMjlwkFW0RyUu?UIThCvq+hDrJ zyurG`cE<3fQ9p~nke_cl%DiNLllfTv2P5B1(mxsS10AdJKuH z3?9VVBJQZwtZ-Ba7x=Nu$r|V=vYWin#!xUul`;!pMV#fQXG23akyyzv2aq}wQXmen z=R^`JDo_jG9JyZe%yoauwlzzM-~Z^Tpa0jhkCuW4{D9U|y*5oh{QUk;-n?Xq?wWV7 z_wdhfc>I$3>5HrT#)F;}hv1|DxEw{7%Y}jl0=h0u0)P>vTah>VL0D|{Mm~^ek&RmH zPSXx&UW)^4(eL9_s%S(*`-5=|hAwdo`ot`k1ppp~b>^|GqA!0Q`(mIdR2+k#Jrdih z!ux<`ox)MDd(Zilq`ExhA1FC<75XJAHmCAol0T)Wk@4jnk35o`{%+q*xsb2QXEH=X z6FtV$|7^Z?=x!2grIg#|>y5Xa>=@YyzIL)2k3se2cKSKsXBN~0 zE4OAt1a`sr_MU%^o7!*ec-X_TakilDaCa0tmeUtEJYapmscy3fnVwYA&Df(M4;7s# zwAH9#pH7^oo(9?+bzZ(FkeHHqHbE!GP07!82VET1QZ&q-9koxKwk^6#iRd6%*U#qb zgZ-K2u9zM2?|vy8N{4533ih0Rn|+s^fz;a3z5RXJVXAK9|Lo~2A9#Ic?RO*7L-vJET{ah6^2EdAho;$P zS#*z?HKu>3ce&bp^SUz)7@vPfdFO%qj^umWbs0yzYxNhA(t_0sBbLDn`10T6wKF?F z`@*oI%fPnE^;GQc`Ir5&i=I{$XsliHta@P}Xw>+!_x#|g>&J(?I-7K6Qy?DcUu^Z~ zE}!>b1JylOK1cNezM27FKLXjDLx*I0mmUApfz^Kww*&mWLN<`2q*gDiZa*zIg$VxU zf?;>7*B_LUt=?=}GdH?P16&a7G+4KbS&5%s|J4tB$!) zi9vq^!n_qbD#BdRfXA9@Dbh)hYdUcJL;2rRF3{%;1X@icC1IRF- zd&&TC)PjyPAV(#gu~p}d1jAA==nM)|9bSLuZQfu2@(jHZeg_3hH6me6Owl-l+8t~x z5PV-S5=xIMAppQz#WHN2q_|Tm5=Zy~co<}=e?``HwBq1XoPJy#K{cYxDCGTMDV1z) zPNqtmRy3%MIjyZGxu?s^Q-uX(H(TG*tQ8N^yxT$q-ISc`M`e& z3}$)@7ZEPiakzEX{t2U>w;FZ3w88a1F_%7fkEzTlwk z2HOL+Ps9HTb4)NAjEeQag4l2E&s`K;p1aGY5ksM(*&32;Rw*QhW|+lltF3=JXUkcu zt8=ha6EyayzoNMqksko7LiGtc>TM{*G`4CuPWz-B6|3>hk8O$_iP5pf0-;5%wL04n z)E++q!hsM}W0B}ACr*HE0uG;}Bq|2~%~{0A&v(X7=eseBu@tWpb)RTe*57_3nr5o|? zOSk;A>F{^9O)GauCJ4ZkU&;H&mqjmEGlTwgT$G}`PLI>bs?R)r$`jN%bhOvY_3o|z z%kX;6?WM5Jptb1mo#pRzfq3==^GU$m4rDk@+^gQ0pSYqR|tOAuO1S)?gguzpT15N%1O2?`~Y!Q9ttj#768U{2b<${*eBOvRdqMx!>iUHbxV`q8R_(u7>rshz++*R(y?|IdA=K~hIfs!R%O+cgGeqOLTHu3p#x<|%d zucrAz{K$E$0Erpde^miSa19#DE)67C{OsWROGhDtOkE zTyaQGE!2*@^de@?ynLkmCGKxry!+Nm*WZ0xgt`M;%4gnr3G&3?xGRi9ywIWd z=8uOn9p0J`Bxlg1C=C#*h9wmlA(P0b116n@rTiYgMdCahwJ4#@*BIDN$aDfXNu3{% z$aF-&0zsonUi4Wv3DK~?Uquk;oVI(8mKA@nIm2;q8OGTt=E6`gF)E5wkWW?#I#$9j zkOE!Ni2+|A`D82rb5>xSLoU#P0f69&tPnF^a8dWgckNs@;mY!J7vv*(t;IZ#J<77} zHFM@|ed*5!8xnGT`>L{OUB|DF3?G`CDyv5xQFV@|k4#L0^%}sPYSrfUV8ds}UM_z> zVX!rn4=>5^ko-yDTMh921Z)riwAVM}S(>CfSxC}5QV(SgXO3llLw%C@GQ~|w;RZg^ z;T1m!c@zSLjAvNPW2HSRN6r(e5~Eh0W(1d0lh1JwhHk0Sia~=a7RkD0SjzzPd8kI; zxigK^1nm^%Rq+o1Y>6fI4Zy+@55j*e35?Gs=_RwA#SDNnCiPLI%|f9zsr=w}Go--r zqRVIi;uZ~1E%CcR$Pxa=6x;Avx{pG?#0OvoZVHka63oZ)0u;_U=GOyH427miIjb|h z;X9je+&H&Z8n;Rf+|%NlQTF!F?#|C#w&8V*f4)MnxZ?%c@o;4kR$)dI=C;9YlO- zgG?)UU~Usa0Y9A#heIHY6IP!kxXFiuzMPNp?eGaP2M5Ax6ZqegmRPuA4jkA66bQL_ z1By60IzV7L>BO;Sy#`vVs`XvS>jTY^M_XqJF7vnSQ-?y>5#Ra@>D&-s(4i{lPWE z_`Ca|4U$-tjiD;1*Y$?%@rv#MjGi2WUGQg$a#A$wk%otO7sLSBK)%MzvH2=(jnR$& z>>hPf?ry%V2IXQnRtq7%zsUlMU25EAJYuAc-KZ8kS^&DiH=P3~PJ-?Sym0X7z-p&r z=|UpyS8}_OjrP%il8%2?Nv4G^i1~e_q}P(*pTY;c@kCIB<*J-2!TWL06!If3&iauk z1Qgda;AtgA*^)mS&;#dS1{6YKl@NEz*=$?jo)FEexDUxRNqD*Fh;?u7on6y<=~e4? zt*^U=Hw!8!7qEs}F6*AU_1kaly|r|wL1$*&ID(tjG+#QSy=s4QL~g%f?xow}8g2Pc z3+fl2*LZ%O#*~1}#q+x+4fJ9v+ zdd!zj+;z&*Dw2QYNsN0yJ%V_Y`WU5mc8BXiZhP&z`oSv4N|seSyP8+)S^Dmtks}jh zU7?8G-`%*ZxP-cZRb zFoJ6h9n2ue4T}=FKvu00br`e@;8KvcNLJnf4=a^`ZJpCD6jU&W!W2VCnGopTQkaqe z3o0y1SrRj#sQ-#HxRPcE+`a%wI-u5tqRk{sQ2~?^lZxPGOJq@JTO?YVgFC9H6l$B@ zeJs`4Fl&F_>`9YD_8$Ca`UfMMIujGqt`tP4a;!KacjjrY(P&kN)T-UnVx^YmZ4@`v zW8%Cz!jmEZv)Ad}NJ96^7sRwNTR~f}_3^WX*{0c!eqX)?>xA^ZucVP$5@oII^3<%6S>>M{kNe$!F5DR~Eg+hXb#$E{Qy0j4<63gtAc^IEL zG|u7YB+3WPgX6YI7*y>S2L{hL9j4;@gCkCb<-bTYHOTlP5@0OJ>ub4Qm?SWPap56i zb1YB?(82_vz?M?Nd3d-ssn))JK<|jyA#PEfOq74iLl&EXFTWP4a^>jV0hKi*_`D;h z@hg8~k0oYO(}4g}yl5n6F*r=rd;LMPO8G1TMpdJqv)=*uG(sf$hA0=!6>UXNQEUvU z)Es-ZBzEe)c{}u%=ZQ2uUlPd51s-3 zMta{Sk^-E0UjsNqOphK-3P&N)PT-G%lfJ4Xe+4jel`eX?)Tq}U+NbkoQe{`rS3bh1 zR66Pp<$qEftE0+qRR^V@+Fy>~ecri_g_~J88;Amh zQCp)OQ-e>F)KZ}Y6|!0;O6;VurIgl^NUDSuwRNHyQbrI(gxZE0lu~M`sVgzHRg;D? zl-4rJ)IMr&8$we06=ofz&zB#5-Gj(+mYly_ z`t@WU;r;5ZF|MGsH*-L{#{4n`pzp~C|=p`?Q|{R{P=5@v0qfnyBNzpB>LES@cU7S?tbkXjuDp>5h)Co8q>*_2jm zzDuX#D?%EWBN5)yjpmiN{rWJ?R3{lfYpC*yQf^PR`zDh8Hl!NFPp)OzLj&4UV}Ibc zhcbZqz#0UqS`ZAJu^kLIt+jk(n-bb^o)SP`w{x_MRBp-sVjr4&CPB7Yo11$p*c1$r z(3LAsO&67#CU(24kEwOZa?DY`r1#hq5>hImx(nkxWpc(nWn-C;2QUWYWyRZFTjG_M&zI=V7 zyV=?$pqlJUO`Z;yWyo;YU-|Uq4=3h#J@Q6q*A-MPw{Z_g?y&9p6ZjKu3Uu#_MQ5ZP zBryj<)34Bt_}t<{oH*C)yvVu+;?H%&yT#qstsLAo#D@>loTdxSOZH-fL!58Bn<{m= zUQs?7)N?ftLw8Sb*6URmrT)0ASEb+Qd-@IQ8nlf`qa^Df=Bty(98#K2OQ4WZJH;gc z`JX;iZe75VTcu`_BvcQPQ38^VTy$nosmf<+-zjMccKqfsAw%c$Z5<0SQx@Lspm?Z#4}NR zR<{(LClQ99sBo%E@=+#wg^9qy)GlBD%kwJY`=Yg3y$Bw0917xZrN;B)Hz6+3 z{a9~_x&ju!D{W{%`$o{~PXc$r4+~{^Uf7t(4u8`7Rc0LKHF%lNHef82TjM_++5V&W&WT)^S6T-T>0E_U>^{(N0X z_0S*EtL%1?-jYhJ&lV6OrTW6M&nGCS|IazEweZXL>wJivC=iR-Zc*$ESG#Soy0Qd* zG4eU1?z4dtjFVO^p+QX|xe0O+~Ff9^L<~>^B2_YQtZrt>Cmbvp0h^YksbzB2T<{cHOs~az}Ug>KZr>_dC3H zYOZRv!1Gu1k?crf)rGyBm8>G}3|Y-^!#9Qz!{rOHTMsEGfsFwtuO;-`g*@wf$!o7* z$M2^#j5UY^(DFH@y{9~cu-}5GBm%Iqz>51IzE)ZmqTAMKH%1KPl!rzUJNSpeQv^8e zoBup2Oct)0D3}z88&h~D3pU5wd_tv$i(WZv;d$n(Z1J=azNvDh?-3NHL2j*Mv{Tdw z6UJCH%IN*F%=i?msn8u9+v{M<<7sOgf0F$XG$Ix4aaq^heFFqcz?n!byYo~#`|B1j z6PXVL_kam7Ljmu{JB$cYnuZVSY%*yEkgiZdvMf%Km0Jm9rF469eV2I&>k?8aNP2EN}v|~7} zvm!E(em<|Uszz@hkZW(Xxbw3B8T!6T^~i9gD~A<6P*U)&&Lc5y`is@21!kW7Rz|)a zn_*n^fJwjR>^4TtUUwpP>JY`bqell9m1hUv1nk>*X^Y~{(OX(U1U3`17>}?PqZT0> zpDrdTQV6(_S%V_@u%V9Bgxt(X33H(vjguQXwc{CY%4!Ij=XyZ~QIF$10wza4h$sdH z^?1TR@18E5BRK|LaEas61U`m=!8oB!X>u@A7}5le=7^ihBrz?8&Br8FOpuze|4K7L z6YxKSKqBCrrk3yYk(hrGq>0JDGX!U?#VQbnK*LFhU?iFh!@x-}Dx747Ad{(7SP%t{ oAeoqA0ha%_qIp#liv>jA3W~ZFA4Q=85J;4nDL_ZZj$jY?8^@(;r~m)} From e5c36ae9e929aaf3caa5cd54d5801d9bb6272d83 Mon Sep 17 00:00:00 2001 From: Joshua Miller Date: Fri, 21 Oct 2016 09:59:00 -0500 Subject: [PATCH 32/37] wip --- esbuild/graph/common/builder.py | 12 +++++++++--- tests/test_suite_data.gv.pdf | Bin 46220 -> 46227 bytes 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/esbuild/graph/common/builder.py b/esbuild/graph/common/builder.py index a0c3df4b..64e9f67b 100644 --- a/esbuild/graph/common/builder.py +++ b/esbuild/graph/common/builder.py @@ -110,12 +110,18 @@ def build_index(builder_class, psqlgraph_driver_args, cases=None, # Create managed cache caching_options = builder_class.get_caching_options() - manager = CacheManager() - manager.start() - cache = manager.new_cached_graph( + cache = CachedGraph( caching_options=caching_options, psqlgraph_driver_args=psqlgraph_driver_args, ) + + # manager = CacheManager() + # manager.start() + # cache = manager.new_cached_graph( + # caching_options=caching_options, + # psqlgraph_driver_args=psqlgraph_driver_args, + # ) + cache.cache_database() # Map work to worker processes diff --git a/tests/test_suite_data.gv.pdf b/tests/test_suite_data.gv.pdf index b35d5dc4daab0505e17296a85c7c793f0017abcd..7a67ba6136d769465ec2e6e705e15e5250f832c3 100644 GIT binary patch delta 17877 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 P2&9QIKu5>c#SZWfx67ih From 764c3b3844ceb2402bc08fc6c2a9c6bba6d35eb5 Mon Sep 17 00:00:00 2001 From: Joshua Miller Date: Fri, 21 Oct 2016 10:00:35 -0500 Subject: [PATCH 33/37] wip --- esbuild/graph/common/builder.py | 4 ++-- tests/test_graph_active_builder.py | 6 +++++- tests/test_suite_data.gv.pdf | Bin 46227 -> 46230 bytes 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/esbuild/graph/common/builder.py b/esbuild/graph/common/builder.py index 64e9f67b..d39858d0 100644 --- a/esbuild/graph/common/builder.py +++ b/esbuild/graph/common/builder.py @@ -90,13 +90,13 @@ def start_worker_pool(builders, cases): return case_in_q, result_q, pool -def build_index(builder_class, psqlgraph_driver_args, cases=None, +def build_index(builder_class, psqlgraph_driver_args, data_dir, cases=None, threads=cpu_count()): """TODO: docstring """ - index = DiskGraphIndex('~/indexes') + index = DiskGraphIndex(data_dir) # caching_options = builder_class.get_caching_options() # cache = CachedGraph( diff --git a/tests/test_graph_active_builder.py b/tests/test_graph_active_builder.py index eeb6f98c..e75452be 100644 --- a/tests/test_graph_active_builder.py +++ b/tests/test_graph_active_builder.py @@ -58,7 +58,11 @@ def cached_graph(psqlgraph_args): @pytest.yield_fixture(scope='module') def index(psqlgraph_args): - disk_index = build_index(ActiveGraphIndexBuilder, psqlgraph_args) + disk_index = build_index( + ActiveGraphIndexBuilder, + psqlgraph_args, + '~/indexes', + ) yield Index._make(map(list, disk_index)) disk_index.delete() diff --git a/tests/test_suite_data.gv.pdf b/tests/test_suite_data.gv.pdf index 7a67ba6136d769465ec2e6e705e15e5250f832c3..0e6c14d8fd37bc071174725bfe98af9d86e7afab 100644 GIT binary patch delta 17574 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 delta 17567 zcmV(*K;FNW=>n7K0Q? zggdxkj0*w-HiiUj3p`3ojdiOd-^$d)~&g03DTiWh(_|Fl?yIK%Aa`zA-rYL(7IrGpZ6lf z_%FQlqLt-+T@fL6f6GM|ufMRoZ+!}(o^?x?ELdFLM`xg}T?!rLeOwK7c!sn+=JJ^o5R5#aw2Ioq18x*ZbxcFApw4k2yvgNf1XDS93{u$@0knd{Ar%C z_ysoc%Knd<<|_5;#n&D!%|EkUf43$D9qO~^lUjvJ(4~K&G`}=ofA_f~%5_jQjiAcp z2#O_Tqxu)KuyGb{c|C!5&cbr59-oHOb4nRhNeq{v2E*H8#HQuF9mXx|F$O%w|?k2tgndR9Tt zD(G1SJq(%$d(+?v^I(rgQ(=!hb*i$LgS{5m%PD(Vcv=?rvdUh7;`d=*egc1lC*v6h zje+M@8v;+^UOX8sL;+m6?}n*?XYd0ki1heYrMylye+2a(1og**`dfqgYl8Y`@J(nM z9KKj7v22*8e`lJ$eVV>yn!aJ0{z=@3;&7Ojt#SR+as5bK|Kqs+>bQO=u209|>b+

OEfl2;O+ec$;yX5vieh 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 Date: Mon, 24 Oct 2016 07:53:18 -0500 Subject: [PATCH 34/37] wip --- esbuild/graph/common/builder.py | 17 ++++------------- esbuild/graph/common/cache.py | 2 +- tests/test_suite_data.gv.pdf | Bin 46230 -> 46221 bytes 3 files changed, 5 insertions(+), 14 deletions(-) diff --git a/esbuild/graph/common/builder.py b/esbuild/graph/common/builder.py index d39858d0..d6df5967 100644 --- a/esbuild/graph/common/builder.py +++ b/esbuild/graph/common/builder.py @@ -98,15 +98,6 @@ def build_index(builder_class, psqlgraph_driver_args, data_dir, cases=None, index = DiskGraphIndex(data_dir) - # caching_options = builder_class.get_caching_options() - # cache = CachedGraph( - # caching_options=caching_options, - # psqlgraph_driver_args=psqlgraph_driver_args, - # ) - # cache.cache_database() - # builder = builder_class(cache, index) - # return builder.denormalize_all() - # Create managed cache caching_options = builder_class.get_caching_options() @@ -123,6 +114,7 @@ def build_index(builder_class, psqlgraph_driver_args, data_dir, cases=None, # ) cache.cache_database() + return builder_class(cache, index).denormalize_all() # Map work to worker processes cases = cases or cache.get_cases() @@ -1095,14 +1087,13 @@ def add_cases(self, node, ptree, doc): return relevant - @lru_cache(maxsize=int(2**20)) - def get_node_annotation_docs(self, node): + def get_node_annotation_docs(self, node_id): """Returns the annotation docs for all annotations relevant to this node """ - annotations = self.cache.neighbors_labeled(node.node_id, 'annotation') + annotations = self.cache.neighbors_labeled(node_id, 'annotation') return [ self.denormalize_annotation(annotation) @@ -1119,7 +1110,7 @@ def add_annotations(self, node, relevant, doc): annotations = doc.pop('annotations', []) for relevant_node in relevant: - annotations = self.get_node_annotation_docs(relevant_node) + annotations = self.get_node_annotation_docs(relevant_node.node_id) annotations.extend(annotations) if annotations: diff --git a/esbuild/graph/common/cache.py b/esbuild/graph/common/cache.py index c14ae267..c069812d 100644 --- a/esbuild/graph/common/cache.py +++ b/esbuild/graph/common/cache.py @@ -436,7 +436,7 @@ def _iter_database_edges(self): .options(joinedload(subclass.src)) .options(joinedload(subclass.dst)) .yield_per(int(1e5)) - for subclass in Edge.__subclasses__() + for subclass in sorted(Edge.__subclasses__()) if not is_case_cache_edge(subclass) ]) diff --git a/tests/test_suite_data.gv.pdf b/tests/test_suite_data.gv.pdf index 0e6c14d8fd37bc071174725bfe98af9d86e7afab..fda71932bbf3bf3baa3a315f68d4fa504c383e09 100644 GIT binary patch delta 18158 zcmV(vKm=E0e zq{v2E*H8#HQuF9mXx|F$O%w|?k2tgndR9TtD(G1SJq(%$dsE>F^I(rgQ(%ugb&9f= zgS}SR%PD(Vcv=?rvdUh7;`d=*egc1lC*kP_je+M@8v;+^e_lKZEkpraz3+x8foJdo zD2VjbQO|u209|>b+S;xNPmdmLEX1 zdSA;40LKcHQ4TKOmp=i$4f|$Z5NK25{MbEfP$y6Bf0^FbvK$PDvP{XQ{F zJ+d$Geika(5qLLyLEtwn69Px!4$sd#5qLIxao~xRa=}BLPm!mf2XPMHEo%e!XSWCL z%ib9He_@MqcvoJz-|aJ%YDWS(4+U<7+pNtDWbcNcIJav#>% z^D3U<0dINh@aXU4Bw-9zl|U*LLrO+z3qTzhXo!@E!aN12HH=5EAHuiT2V0%3<`z@2 zyYoL3^Oer|oyq_7=Nr1ccShgP!@mBZ8qyf`_4f|d%?O^~cNqT>f7I1^7=KKve%KfB ze;>Q1EB#_;f4{SLXyVkqVf=B|vSB!|Y{8IB4t@+BL-GPRp?By!Vr`#x?hf`Xh=z{GUMl|DKxj%Fc{o>?LFi`aEOl1U$|%~sTV96x<^{lIdrYm8QeQpx$fT%-%Ae9l{)vLe|x)T z_U*k_UedX5t~|F(f(hM!!!4`3zVWOZ&pm7PE&t(Jw~(8yCeOM-x$fVd)kO~9K%Uh_ zp4CO3b%T6^@+>m?u4OaY*ZzmUb(dXs!P>PKAa)(1*k0s=%}L*ZEC`K$2-`{6J}tL{ z1^~y(PmjJ$`+;T-kc}$0mQWOVf6)eXC&-fx=mS)T9Kgpv#4WIY0KJZWizcEu=qS+E zBX}IziYB8XT8W!c82=L0qb~FV^bB0F9<73NyU}-%2v_!o|=W=u@PE+efe>bBRc;21p z3G@NBkG3EiszoK#i7rA*(Mog)`ZgSU8oh;njlD3MG|Itqy3uTO6WWgMKtt$79KcuM z?=$MrrK8KydGH3y;kw&kG_RvSqQ7Djeipwp>K#2WIttI0Py=dLj^B&Ek9MOUl98a7 z;CBL@#53@0TB2)5^`kYTf2ZMmBS1|?z3650lf;p-@;SlxE{~Km*P!$ zD}IS;r!5S}P9D7u-jWA+H^XlVy#HEw(`{%6!00H$Lcx!_&>plG9R}FFg^r{5(FiJIKa8`0+wmNHCH@gUijU#HQxqjo0eEJD z+Dz?)-x2B<^%m`>e|>bEuBI=bZ>M+C4>H@?#q4VKd+c7-XWW+ZqVnSMVEO9uQ=`43 zcZ@zddIa7^gtsAc+JnZ!Xs4l>FoPGOD-~F8CAb9dvmYIV-ywLbC(%>r7`)r>(J8>W zGXMv*0tY8RB8Q8(gj?V}J8&l+4{Fa8JQL<;Htxd<@N&EXe{aO!#`nVS`*=5u;{f~) z<0tW}_;vhi_?^I?!|(4DOL3HwlBg&pQ@!w;4Zj7{B5EnMj9N+E0>1~SJ=6hem_~F9 z-Aylm-w=I-evAG!{agBwk;Tdg^xSUuYvW4(RM_f8fwJ&XnQI3;*p*xpJm_?o2EM zOQ@7i1-qo+(9b)i;4q#utq6S@S~!HH_90_(>~eA)utMg!vd^BZ3s%`URLp^QDuYf3s)7SdS_q ze|&++K{B1^Fk%SEw1ORAqosO>k$P(1UW~ufPxQTE)ag46Qih&)L3$X)2|6t6gsWjE zk%EpY5n5HLU^l#VH<`EK*5KChi?;^5gG*t;nTS%ufhAk}voM?)eaoPn*(VOk{ho8p zCH?)4aGxZ(4_pGLZ|#RWEFZfA)Jj)&e*{iSrFw~IpV~LAZ)j7eXGres2ao`Y9hurU zbOf-gzaP$mF^;_{)EkyL$KE*u@0_lJ0O8-}d0W>cGnUERuTPtXUcIA)*IgtxmZsY;If6Rx7hKs;D z{^nm0c108dO)m_(P87x99TFfJlPCr9GXq*^4rFEx=%uxw2iK2jLXF?N$^UQnnm~6Z zfAwf1XiA^rrT9f^CiOAsDW{mLnP0MpRCBm`?sI;VTBF{lkv0FNy;}R4u2%O;eV_hc zhJD6Mh4Y2i%o=mpqO*L*f9kdV!FHYPOZ#!hM#m@4OI;b)mF^2Yf@h1j!TY)I5`Uxr z-avie#o)u@cS4!agVLICBj}hSSRr?S9YVt#cO0Pbcvc1O2-%AmZaj@NEHj>_DYsh1 zjmOBvt3MOFr#q9$$)`$_MoN=~FH4hzkrHYxjg*8_P*msgCeajwe@$cuhfn{D?fuum zVfx)O5f~*#7nHYCtJtN0D_yczr)OwAud^_WPEVWk7K_8-W`4r=m|SMdFxKuDzg2nA zq>)pTyOwl*j9OdG#UeJDi%_AT2|ugOnJx7Nhl*2~1c%wdMProdg4Z|w#In0Fq6u->)4jjUGyV$p{{9olq z0ajD-cc^ic0p=wrYfv+d-7L^FJB;@LWR$l!A$*LolTKFWETT=EivM0#Q-)12E()1P zPttqY`Cys&(QR_*QT&afWK?;>H#zmHk)c=loX;>Hmk#)Hxs3oqr^}wY7z?dd1}KY zV#~u1w~8To=)-H4v|LvH-3!-jnS0e}1k8o%zkL@Qf6AYJ@4r9XQf8a}`uxaCL*;|} zpT#|xdSZm&*oVNlBJ2ggg;vR~LF)}xDr&8_Qo50a{O>~aKNoVpldQi3zvU(SEDNpR z$COQa9ZfO3jpaF=6Xu(uhjH$pPN#P{oKN8^kcjWc185BA0olhUzSL@V6eoRg@(lhW znXJwse;AnEX0qBHHnFY+*O_XgQb@(sMe@`_JpIy)zCC@(@vMk<KJ>;P$~WLw zf9FrGcCR|~dk4N6FMjBI_be`~QGdMut-J3lzh1s7)2}Q42~Zkf(?9xGdXQZX5@Cm2 z8tt)9FBT3Wo%}(?MBu)E5akq!*80<8$E1xOF}QK@Uts+MRD|L3WO*4f5Pigic;^b&H)7gkOn?_vqA*GbFu@??)NtU zz=V;r&?*vGxt+j=06zxm?fIJey4sjB?J)FzhXMe^P7oc5p=e!geg5r(tv7Ee47{&* z3e>LQ?+#otGgB9cAHVgkA9uy3&u?5=eyjZXRg1*PPu4uWYQ?l0G39Q&{i>B~f2O6* z=k7f8;3W&DWr~Tyvfa;=KNw%-Cczw_dk5gpOMv?n$mr|kz!fxR^(sb9(RzgOTC-kH zV?EN*j0Ry^1@VD(!1HzZj)NMS)#x!5VVa1E@~`V@}|5^GD#+}j+#}r z;m_LVz46A*kt58ukqPv-&s=?d`4K$pdS#B=Mn9#mVXpz%|C$`T!Gr5~s}1y#goCw) ztTwGqZFIN=qj9a-<8gbS#js#b;2PNk^w{ew^ICErb&r(bRX1dvp9?2}0vyH7hD?%GMo=WSeIC{&`l4tqU}L;-UIvQSuG)wS2+G2{>;fE-c4jeWp&+q!SUCUE6bsRqyl)S=ZCTuHjn04R84KsTt zlwbJk!qVbo`tfUD{T`;*w9;x`%i<60e#2okyT|LQnm%stqW8=1SOQc1=?ZRi18kpR zuK*m0plz}=*9g#6Ya9{5W1X_fgFW3IO4f*KHnfYl#k;H*o+s9yeT@SjO+PeWz-ye?^we{ zkDgz@@kiyCU)@6Bfl(Y}B++|xXpQW>O0${&5l1iM*6~}pZ>t$z&FhewSA+8fq(NGC zm?;W_BZgLE1Hue@AJV~|4iU^UATlI#9r^XBXW>F$Q)uH7k?A~k_p6_u(OV) zHH;?a(!0VXrZHNI&0*)d=DO$Rmov-R<*w!K<$0l#&qtjsW3(xi*1RjgYImjd#ucH* zsTC-(3p|d1M6$Ndw!(XeU-4`fLllkMTUQIXG;oqAe;K4y^bC_CfgBYas;SEOM8T>C zKBYN>ND42L4<a79BnJW+l#MX3$QNQvq$()fVat)ZpNT=gyma%gPnumdh?b|B74Imj95O@a~@7 z&n#%zfAH}3-yHhUpQhD)E3|3;%FQ>{KRWfsAJQ%9Nh{}Fzi!3_yT@r-=db(r@K4rW zHc;2K@yTnp9XAIgMVzF;N2bg(V8eKWli!tOoqBc) zGGP1y8^e zOwvgvp(@fvrl=|fO2Jv0S&p0Oo0%>Ae+}wy>Az+8mhoG{&4HVPchh$>+x6QG+l||W zy90Lz!=3t01I0nO6FKa5OgWvfxm=j>&_7lQ9;4o4h-*Z6fH7!yQBE2GySf7N>L9OD zrOa@mTBAvr;YyW@wuAdtWDVG5*Qgk05JPf7%HbTwvt*rG7S%i*G#Y4LYEy%7e>LD2 zKtlJxaA-=6LfKPp*T{&IaFY`7laiYlSsCZVRs#aTT8u$oE#N#v4#srX+GrMwgl0f8*)Vh|{v0UX^SCV8 ztIIXuxS>#f^aF@xEK)oxkIL@fct3W0=%o9d%bZl4w>wymYNO11e?*QO#%*#4cBtJ^ zJ7)xA6<{gR=8Q)j4hOgeI~~tDe&L`&8&K_!8fONEDRyr(qA-{8zzF~!Vc!7AiVld} z&7ZiPrvT&J%_p61VD4i~#_J8~O}>a2HF=E%qz^$M_{{}m2 zitq=m0Of0dD-%0ke+pJiL@`7!`PAU6)g&$1MEl0KeqH`E4!pPXhDql~JC{8Av+|+m z_CNg+ZspiT?ZHsF_Qsh%C_h?$8w~5i6O*%}=e1q(tLJeTCtrOF;6(f%8vrK_pqJbw z*SzGx5AwtOu=}9rpFCU7n?<8191mMWk0UObEtDn$)&)gneCp8q=fVEMDI>hjf>cDApf;@I(1 zeEx=wQ_uVUe@7!PT^yWu8#wNpc5d5gPhoz zw)(6F+7$?^ospP^4o5?b#lRb*dqSDGF~eIeDWBgTe^2m$h=~O4a;{VNYSy9X)F>4l zrZfkW=0Jj>2{4mYV>J8az^PNGN(!>Il8ONMq;QguFR150vA9COgg+wTivfJ{^JKD8 zkL?m;gorJ$%Yh^i`cQcqkRn{bG7cJ2g;wOZMf-MJ@#DA z(Q{q-e}zd$UVm{)ap3f0)cFwwfGa!rX!-b-slIr*F!}Ow^zun%w%I;+Px%1=A^c%t zmoW=qCyXAF=ln-7PCx|9{vC_~(IdsB3NYz_KMY_z2S16Y!V;(k|5EqnG*dONYiJDt zUi2LB6e1;n`f^|r0FP*k1sBLol$Xeb%jx7Ba(|Y0~W<}nOqi_RZPt-kX+70IG0O?cS^sIsH`+adRC&P ze_@K*Ut^q^Bz&u;dQ2%AAV>rUAyz@upH(&ek;7fSCe+bMh6f95MF@6)c1|BMZRDRB2bV?ySZm^My zMpIjg`ZGz(@CX!(RhiLOrmh}-NdJhOqy0ghvZK$Z4a&NQ*&SQD=(0bq)& zJE@hx+KQ_?I#!Row7zL%dneQtT)U*5k4E|SOUkS9t!LY3R$tl*Dv3_M9)G7i=TaFk zPvQI2H2@nDv*?rK1Tg6kVP}@Ke?o_8$sl^nP=cG9v5*m4%)HeOgO$|=U~j~R9j^Ob2VJVKUe|qg?pzK#ZJ_N|M$bFz>7J;@Ps z$V91m1|0%M5)l`s2P#GG2KRe4=nhc}@u zYQX~XUgUj64LJ`Qtu_S?e;%(!txlNzexKi?f!Kte^XRlNBqTX#tHYiI{^ie;`$nCyEn8VTsC&0l|O%xd5IYsG76x zm)%a(>L`sk$Q+KHz;Z&80hO5*k^)aOX7KcVHL2j;It!dJuP>POe_BEj3HIJO~j*L_XSCs=1eg6+>c~yrhdiw8-I?8vf9K%vg*LC!rr`IqS zocYCrc~J*U66EpdC+vd&JFs@popSqcoVd@m)b+mhQ^TjWkGv`^F*;l>r%UVPT?~&b z0w{K74dq9k0Pj?belp%TWRP;=gdhDURf2fH@b#r!~euY_d<_`)a z2vI0>%glnN0b+$O$UQH*U-43hTtD+sW?AD;^5zLfPwcF|77{(tv}6wXV-}hdGyaUG zmm9}L9kimv#iG1nrr^nWrg~@(A&`VBG^WKR;^zp2XmLc3gAs$T>y)B%5C|yj3ycK6 z%cs>NN*BRVf343j3sWvA^j^&@2z}DCzEW+kMdN3#m(}V3HxKb#P{fMcoZu50GX{XZ zK*y_ttf(<9B?yKC16~QK!u{yMAI`qM)mI1!w@ll9=8?-9+b*HJn8DWaYafdjxyD^J z@;tM>JL*b~e9BVs@h_j5tQ~g^eff$`b@Y|{-*}2Hf8V^WM1(H*ANp z?2}Twfw>|YGEzJT&U8{1YZQZw<@8CUC@Y65Xb@MxHlXF zS2}9_e-a{0!h2vUxSfi{RSLzBJsOL|!Z8RAMfFir1c$W+MB7==kPXlRlq+Bq12vhk zLSc7kbbJA;%us+iMgkFvDFL%Hra2>U9TFo#3PIXkp?VluvBd3alR{y@*enK9 z!-ON{!v`@gpV>D&`pIigV=ES(dE@$R<$qi~f3)bqnGcjlmo3|`aX&op7+zR@6{nSy zwW{)~<)?7ZiwF0=P(E1x*TLuW`+KXb5%69fVRciMJPF3PLcbt~n*e9E5ZV5Vd_|A@ zZ4VXm9+qARy%{YT>E4eAs~hZlu0w& zos7y6VWTQLAUxyb0PD#lfESKL`@U}Pe}0AAH6#|I;wnxD%vCU)S~u@Uw@towcC5T< zu(53wRoFZDyO$op55y)nmk*VlYe1!ZiFzU0ad=;wM4tp)hui_2m7^wUz2++IR_#{ZAHyF-xL&?re={pW zX*FErM$L`-&5?ICZ$`NKVa&<;x{Y#w^|ETJdUq=0Aw2>2M)^GZg?7rmJ8FqX^csc< zWC|9V$z;@Wt*34nFO!YPQ?C~^kx<;j6{9Pz24eD;XoRP&i`H^HrKzI1yKCR4HZ_5={Yc zY!KQ3>Zvd#qP!5h6XM@Qqb2SNg+@qpqUNlQ3l^Aq@7C$J zUcGAZgzN!o7?7rZf~=RxO>~cg5~^dQvWYfF=u>z@~!yVrCd< z$^r4f7S+qNhuVYpP}EKge@l7hVOW(DzyXRfP4MW`As*tOY02`k-9tGnCP;SSd6Qmc z$v|vLuj5@n7yGDQJdAnS!0`!lz%UA6jr<^kjCMZO`N~cbp^YSYi zlR^&Yy^>;c;sN**PJT{;^2EqYf;s?vrVKD*)yLrs6( zMXqI@%UxG^cAy=2r*WrnKe``3px}4|Ad~ID_4fdcx-s~|w?TUILKdv%*gt%7ngaP%YQe+c3D$T03c5JYb5ei9s{ zn~)kmCu@SJVN(Ou;3_r_<3H>dFFjug&kwj=lSbUm5vWI;XT$W00~Pc+P|6kG9@L=Z zZl07$8Xz*mZU*P+|7?(;4e&RhJaUcOsW?*q&k7EFso+%QONJ5;HSBDzsEVrxfc;^` z>H{Re7SM?lf31j^fzYAGASVcI5lspDIGUrS7>y+@rl1dxHoG%gEsh^w;HeL`QQ=8G zaEd}6JF`%s5qkA+UXD<*YeuZ`MXTFagf5yMX@y%?sLR)AQ(W9eFz+>x` z4Y0C+g4`2^y;(f)eSkA${fyu0EMF&gN6qRSs{!8bEoY5gW(XWa^96 zDWe9df2_PUAK@}B^;*8AS=+|76=Q-n+g2r4uTNyF_Eb?-!xWM=9nP4iGt|y>%CNj< zZ$~>(H%^U^2!82fn7@(I38KG(u2D&KfG#B*ats>E1S@>Asijql>l~P)BKoK*YK~$9 z6GdDL<43lz!w;&4B`WxFEKciC6k}vCvaP%yf0<%d|2g&vN}ZyE5C(eIEet+(Wx^}0 zG+d~URNTJ`5)jX@5_bZ|3KEgn4#WpV&;hz*m8uR?y=!~7m14Q}^=0(k^RdMmT9MCW zG!dIGoqO!Z&viw3eZt|71S1WNoz3*b`nl83+lV(%RnbiU>bXhpgyMBQ|VD?ky@i&5+|dH^dGwN7z`t{$*Jydn>< z8jBH=zxogkAV*Bgm|9)@P+rdVx-dcO}=8d}CAv;51x6eBiPpI(su<&GUAvpdRE1qNAwK`*^W$xnPp9)FYLKK`ibe{Iv- z&Oeww_H%XGF70{RlauNo%PA<v!J!7p!_YMen(Gl32`Ta&>mwOZVULm(JKM(-qw}eEF+iU|6<5@S_@F zbCMl|EX_vruDtTj_(Snm<3CG%m^zhGp_Q4dGdE@K$vl#LH1kCA$;{7_f5$Q}HoTX7 zH}h75flf|LP!g{_&P>&KwcAYopku1f>%UE`fy5ie!GvNpS+Mfi+D68lHsRWQnrm!{ z#YAn0$(m!bl9_-Gl?t6dsKP-1cyFl*KsZ36$)^;T6GV1SRxr!~nv)Xl1TQej)EcWQ z$W~X3r|MFLC@RLGs87~Le{n;i@oUJYM35m6=s26q1tu&G&`NMw}CG{+;Jyv`h$o}LpDA}R_~RIp2H*Q##%KG%>KKmXxhjXb_~{!Q&0 zZ{G1edT-Dc!7a@hiWY4;w~jSX%Zlrp&itaS7E>aXYf@j;>`r6uf3e@-!kGupPvFO{ zTk+c;?LGs%H$M6atm1hXd|4#Z_BZmtGJd&kmHA@ZRor_1O5Fz2HRcW04Yo6eFOB+H z{Du5{(^2Ln^P9}a>OUCyW|9Wt1h)yL*3c?YEFr!;j#hcSi+mRDHq{SRl&Vdy^*KSH z_=I18|DRxQfPNREe`T~5|ON0Hs+g*JwQF{+eV04w4wKRp{7vWdh>hB<)LnUDf;fITOYP*H(e_~yv< znrE(Cwyjx8{QgHz{rtb4eY6xb;0Lsx>a}V5;pg{%^5!K=e{|QpgT04;hQs5R)K6br z-8UZetT+TG1;FJfx?C<4G!W2rX%Ya8DBX&@(GS96t2gq2M2l?HVt1N$IP+Q@V2geq zr&2{D8rmO>V=#1yW6&pNxhw$iFsw6=Wfgt#*cSsuq2d?>?UC4472XFl>lBWH-Fwcb zB-Q01|3Jx^f2+_hQL#Cd50m^UMU9Lv?|9^qSSzL6HeYYN?PSNuM)0+h)p!i5FSpar0Y9^#9$2|G8zQg^#<%x$ z+|+(!$HN|$jk5)Hhr6TLv7ElR;Q{LdPIa3_$n>O=e{RMe4SA^OM4_!l4f}NBJoPlt z=BV@XJ%PlO#Ip%HF>XqJwmazJsFtE(_Ux#A;qf@Zw?Az?S>82uFE*$U8}!{loqUBe;Bb0Uci_CCa;~@0ooUa6`O{~D<7x$-%x z7x2{#`1%pZ<{UaC+q>-epAM{cxEQIdkOJ>1y3bUg`P80zSI1I>4 zoCIfCEK!jwLY!zlFbxWOg=9CoGinb*R)I6(i21=30%8U_CR}yQg-Q$}5azAeQ4!{f z26WC`s^sca5Z^pK?`zQ7^r>rI^QqSAf4&QU*c7auSe`PwrftsT+iGW($9c6)m(WKV z>S!vgkMMqO5Q#9ZzLF&fmzPpW^i6>IkY4WkwpY~VZ zsoOf+G+e-|kxVufe`fJx3-*<2#5~XnEPJ6x+1024{Zbz64)+BIZ8z8+uzec-SD0gh z(O^`p4;I9JYk%&d;PTvEHjNkx70uR=WV1>kIW)s8R$Fb=Ia|(JU7dranxL^q{T0o{ zi2MLp6{=6rQEx*brmi3>`07`H5LdhYOU4ThM@NN5fBc9pc;!r zXE|{KY!h(!93@dP_;1cCJ~$-?0kY!M$ur~t^g=(!3+|*FVi7#VBEA`lQ0Pd(B*z9C^D`V>x}fa!s*5w| zH`-lQDwP;6>8z)x&CYW`C79%VsA}m4VI}*&WN*EzHb|L*KQ>TP5>rZ)&?HO>Or~24 z=?-t=8ThVD2+3gWc~J>wabk#RMBd54aJbPM4@!krZ&Oejf8Xex6qIy9b}9_%He<(l zPeC5v(;*k?(_xR5WprJWEykLz7Dr7>AmA`^lP8s$5^>E`!br40b(ve!ucxV=^e`SL z>$~OpLbmNz`E{A}$RCst%Tr<%1aAmq z2G(4mS;Cu>e@RmYJXB-x8Y1MrrrCnt;RF9Hu|pk%DOK#zuedRRIOtjxU<22NYb%pb z=@BQpn1uKo2bi`|6XfAIyCR!XZBbTocgPK~d7IG?T z84slVf1tnf5Hm!)!M=q^_ehC&8_0BkU!6FczM24bfT;+_SlsE3 zJENfRx?`@ySHf{%Of;TF?^aA^?$#*uT)Qc4TE7j#-+S0^7(t z^Dc@r=XtHm*6Gqh<~Vi8W9&3Sq=Hxr9`~4`W-cnm0%Tq&;7B2dKBB|MD00xYC^o5~ ze`VpIWkAj-wlh!&8gmprIRgbj<4TN2(Ip1lfU*cuP$7dHl2^gArsRr4dTOC|`e>D*{HX%Yk5XN0$9O8uzy*Gb6oayk^d>}c4 zCPit0P&F*6$OxH4J{>UWG%V%!@GTPO;iyFkZNA39c0#5TxJl~#fJCMv0u~4wRq~?G zx=DzJ1^z06K)ThAP3t;-ePsC1+*DaT@`$Q)Jbh$h60Fw%?o_Kbw+9^Bd}u%$F%{QVKWlkq)o;LCB*JC}cdt zVje5)Q8{v+NR=41@-!p3oSJ-&gD`YUl~xQIRIy0bEyG#{pwB}!`p%tcoF-_eD6fit z0ANcjv2OqtmUs|mNnm_7NiUh@EM@?tF{zItZ59f(N#zH(n;`{`7hOgJe-O85fNF`~ z1wxMSH>TKz$I^Wi`XxR9GjLOo%#dI{mKUIK&N06pcw#6tP0CrF=?&l6eB;KswbHm% zYT%w0-;A=ie|C3%=CTd1WBl_Kg2f##;0LCprhazE-s5zqMHg>pFvDn1%XRJ;?-g<5 zV!WZtU;W45y+(qL5IX>1fA0l2C(sso;!!^?gm55%3D--2`060yOB-Zb!2@%f5DNI| zWH=lGVVtn~EWu4a9Q5UUly8Smh&ebAR-3^8p0vcm6?5Rg9-u(T%^Og}(a`|{(@7_e zom>rW0A;a^0?~8GiqA?MMQ9L2Bw9Z}<*dXRb66=DYPA<^qWb(&f23L?nu}LBYU(&z zzFf}B)sg5VyL92yfwD#9tEb}U7tLZB(ORXpI5on3{fnD3iH7dgrE>Fm9TW%xf@@1h zPf|al_mUOFn3hEgvS2%v&=>Vfb<6bYwd-|Tbdcko^H#qB><_LP#^2o!ZIHyGYz$R7 zy{E}Q0!9UF5?j+ZR|$1;L!rm4Zi6dIB^nmKj4LfM+a6r6-yTqX}^-&m29++ z29$KPN-`~ULCo(XCB2pe{}evpjVFR4ELY`J3Eq!`rjQ?Te{t52L?NKKrU6eYDaw}o z*?=B62Q#1$603x`Q_g1F0{4VyUd4S#rb)ufMMtcAbMNe$)=RHiw`+afHN06+Ik|u} z)N)z()UDrsYwxY4I}JKB>&6k>w5Ive8SPb*BXauqDwVEwgsZH1uqO4TWA5zI$Q8SKfF=}Ovs13`0SQ<`ctsbXr zN?E}yJ@y_X>Acqri;zZ+9)qUvHWa9JWbjS5^JRDIF(nNPJOL!?BGF^MbmFd4mR6B0 zPh#8y>Jh}F)W;~jvpZZDa@%Xy)elxVRzJYyhXC|4tQ9p1Z?Y^cA=nxITWTCI?9AV|CYj(1XxgEQOc5-0Y&{+ zoWYeeJK**ONYVkdE);DhVTuZ%l$cZmH(Mf$I@==A(j44TJ*80F?CxW!&W2g@W>1YmBCs96V9vrt# zf5M<@zc?^>#_2E>-ya-tDlGp+qNzc~7m)yCNnT&e^}-~935*L55u0OyI)D}?2nDv3 z63)ZJwMn)1^#giG#13(b>SUt)TOP9541D>uNR=x`?+&P}A;ISzIgMWtdn_@Nnhpe* z;zc7li@{-{-s=yVRmx`(Fsd5;oc#{Kf2R>5(Kkf7Xs&20dWvFWNTufBOMFJ&s?Iq> ziO}WN%~mxmEvI8lfhy1iMpaYi&gF{cbk5`TcqO(cmp!9CU0X*Pz9XYl9i`ykd%NS+6;Qhh^!xHQ^5sHf6<*& z7$NBi7I87^4W%hD3STf8IXEr|%V?XjFRlgv6JWkC5P#k3N_+4O@Hf)?HjxzI%=;R^ zA!2&;Xi_)|iFN{i6pULia7hcum}HLttiPH8h>GS3x{?WqLZnowfRT-*nvuji4=#Y2 zt8~%BrAEE>&_10vlPbG{zVZ=9f2GnJM)>ES20v}Q_3zgwIhaIO!ne9@pnL*fr?ak1 zrX^-<9zoRs-f#zM!h(GGj~s?id|~oo44j~{RL)o5g_`|8(+L2_J>=3vVJMI5*kqE; zzGF+xL!Ra#!h|pj!(?7e9?r7psE~)|VRgvETy3j1q@uX)JfubB;T(%$OySh2WGMIW zYd_rQm(Tn4etrIgkLg;@2HRniOh#q&GBSEUXD>=vtv@Xx*OVptp65dyxWn(^URArv&W*{{!S(>r+vz zZ+$h7AKT@EntY?>=>_=8n$Y(}OZ|jl!H9iBBhm{tybepEGV${q7~G$Bj$yVrn_=k) z&#PzUblLbamwQpg2Aop1F>?kYkHE^I{UcXO-)a`F3VM{SStE`63HsVXI^2YSME)Xe z*ms)FPBXJt$&nd5Xm{T;oWG<~t{S{yWiV`|xlBc^o3qX?znk|kjXub)sH-GzuanYAr#GFU+WA8Y#ojfc+o6BPNe(YbBwm>eK)WAkoBrQ1sB7? zZ$IiLg{&+$R!-zu2Q{|91iJ#EuY$ye7y7S1!ybvN6)0J;@JCO`*c;Bp>(c}MfN;N5%*ZEo8@qk3~n>b(6K10#+ z!)XY|ra!;2Whk)5Tvc)6UOO`jaZRG_fo|ASvPN`u`a)~2G|g~#ap}a}S~brLd)=J3 zvlFz3o8>d-L*V`fc z=z90fV{9i~@n69;RP$Yi_IaXl-L+|>RXI1f+>A`_#0BG^8@6k$3W4pO{xyz2QVr8p zG9Gvrx=*3D+3ZzLzUY&NBGKqcXS&qwU3`cPwQ~|l>SlB<7$E5ldys@>=xu{`Ga`8U z!!#q=?jA;OqUaJYxc$1sm(wXq37L&)=0$R~cpqzDx|tE3Q8{a{z=S@n;|_d5=e042 zx&R?H>jC8-HPpF9NqF&FNH=%2W!&wKaB|%L#;=2-pi{03i0TevNIMaqeccIAT1TkR z>zsn7d=gdE#a+A3$ckB@1EEdo+k3Y(8C3?LGu;P|{5ZKdH>!4PGL|+3=S^ripO{i` zf!^L43*)7UAwGmX0c&GmXGnkodKQ-*W;`=NOa-gs@k4=GEAeMG=gLnfG)!%O*$TxY zX;A~~*GW9JOU8;0pG?p^5~9azSZMJ9b!COJ@JR1kHGW>(GW3_qwsx5fYsH+QG*slD zI&x>ruroYsjLYLK6V^)XEaC>!zEChPY!5qjTDVC2wc@)(uE{MaQ6~cAwJHYr^9?6) zQ!{1Z0dC22X@7{{s5&IG)nV>j{);iz4g!-m@#iN~N#+d_ZII9p_NNvFU2g4TSj=5T z>bMKKeKjxt9ufeGogEEI=wrO2#^yl@mH~t;*}nSFev8huq0GNp8)N0YEgwlw6!aI& z3XE~z&(0gj+%DuKi&@$%rqJq2Ubc9!S1(W9t!TF8{jsoP16hqwJePJitbeg8=<@HnJKjph;&OC@zYE3iq=X>*`Ne9*e8D52HTEu5WWzvBTL z*jt}H@10b%Y*~*!xu?+cY@GB-Us&1VQ!(+rQ|wm8tK9~3wtm@7))(pC z+*J#Xu!8+{A+=7Kk$Ugzgif6M2_*2wrDHn?Rfhh=th z3lF=lfug99wB)2HQvAP^aE1ax0uTh`Kd`}K(I93@<7Fi*3V{ZgicL2aY%tC2CIxw4 zgf#^5Zy;0%=sy6^fEDIj2VlQ(XoS_b4rR?;Z?+?1B9SCC3K>a8k+BgdbQF?|0kAgz rlnoL9tVuY~QSARsAfXT(4n#{PB_*dNMUg=O+8TobL7~pxE}*{wqxKar delta 18128 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