<jupyter_start><jupyter_text>Graph Utilities for `neo4j`  Preliminaries<jupyter_code>import numpy as np
from pprint import pprint
import neo4j
import hashlib
from hashlib import sha256
from pprint import pprint
import time<jupyter_output><empty_output><jupyter_text>Utility functions  `numpy` array store<jupyter_code>#from collections.abc import MutableMapping

class NumpyStore():
    def __init__(self, driver):
        self.driver = driver
    
    @staticmethod
    def _np_to_key(a):
        m = sha256(a)
        m.update(a.dtype.name.encode('utf8'))
        m.update(str(a.shape).encode('utf8'))
        return m.hexdigest()[:16]
    
    @staticmethod
    def _add_np(tx, a, k):
        tx.run("MERGE (:ndarray {k: $k, dtype: $dtype, shape: $shape, bytes: $bytes})",
               k=k,
               dtype=a.dtype.name,
               shape=list(a.shape),
               bytes=a.tobytes())
        
    @staticmethod
    def _get_np(tx, k):
        response = tx.run("MATCH (a:ndarray) WHERE a.k = $k "
                          "RETURN a.dtype as dtype, a.shape as shape, a.bytes as bytes",
                          k=k)
        n_matches = 0
        for r in response:
            n_matches += 1
            a = np.frombuffer(r['bytes'], dtype=r['dtype']).reshape(r['shape'])
        assert n_matches <= 1, f"Found {n_matches} arrays of key {k}, when should only be one."
        if n_matches < 1:
            raise KeyError
        else:
            return a
        
    def _tput(self, a):
        k = self._np_to_key(a)
        with self.driver.session() as session:
            session.write_transaction(self._add_np, a, k=k)
        return k

    def _tget(self, k):
        with self.driver.session() as session:
            a = session.read_transaction(self._get_np, k)
        assert k == self._np_to_key(a)
        return a

    def store(self, a):
        return self._tput(a)
    
    def retrieve(self, key):
        return self._tget(k)
    
    def __getitem__(self, k):
        return self._tget(k)

    def __setitem__(self, k, v):
        return self._tput(v)

    def __delitem__(self):
        raise NotImplementedError

    def __iter__(self):
        raise NotImplementedError

    def __len__(self):
        raise NotImplementedError<jupyter_output><empty_output><jupyter_text>---  Tests  Connecting Need to get the `gpu-jupyter` and the `neo4j` docker containers connected. If run bare, something like:    docker network connect gpu-jupyter_default gpu-jupyter     docker network connect gpu-jupyter_default neo4j    docker network inspect gpu-jupyter_default     Docker has better ways than this.<jupyter_code>if __name__ == '__main__':
    driver = neo4j.GraphDatabase.driver("neo4j://172.19.0.2:7687", auth=("neo4j", "test"))
    driver.verify_connectivity()

    print("Testing ", end='')
    nps = NumpyStore(driver)
    test_arrays = []
    test_array_keys = []
    for i in range(10):
        print('.', end='')
        for j in range(100):
            for k in range(3):
                a = np.random.randn(i*j).reshape(i,j)
                test_arrays.append(a)
                k = nps.store(a)
                test_array_keys.append(k)
                assert np.equal(nps[k], a).all()
    print("Passed")<jupyter_output><ipython-input-6-4bcb514fffa1>:3: ExperimentalWarning: The configuration may change in the future.
  driver.verify_connectivity()<jupyter_text>---  Publishing To produce an importable `graph_utils_neo4j.py`:1. Save this notebook1. Uncomment the `jupyter nbconvert` line below1. Execute it.1. Comment out the convert again1. Save the notebook again in that form<jupyter_code>###!jupyter nbconvert --to script 'graph_utils_neo4j.ipynb'<jupyter_output>[NbConvertApp] Converting notebook graph_utils_neo4j.ipynb to script
[NbConvertApp] Writing 3571 bytes to graph_utils_neo4j.py
{'fraction_non_alphanumeric': 0.10981004423627375, 'fraction_numerical': 0.015092375748113453, 'mean_word_length': 2.5791433891992552, 'pattern_counts': {'":': 0, '<': 18, '<?xml version=': 0, '>': 16, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 1, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '4', 'dir': 'jupyter-structured-clean-dedup', 'id': '286144', 'license': 'MIT', 'n_tokens_mistral': 1308, 'n_tokens_neox': 1265, 'n_words': 312, 'path': 'nbs/graph_utils_neo4j.ipynb', 'repo_name': 'pramasoul/aix', 'size': '3843'}