Source code for openpnm.io._jsongraph

import os
import json
import pickle
import logging
import numpy as np
from pathlib import Path
from openpnm.io import _parse_filename
from openpnm.network import Network
logger = logging.getLogger(__name__)


def _validate_json(json_file):
    import jsonschema
    # Validate name of schema file
    relative_path = '../../utils/jgf_schema.pkl'
    schema_file = Path(os.path.realpath(__file__), relative_path)
    schema_file = _parse_filename(filename=schema_file, ext='pkl')

    # Load schema from pickle file
    with open(schema_file, 'rb') as file:
        jgf_schema = pickle.load(file)

    # Validate JSON agains schema
    try:
        jsonschema.validate(json_file, jgf_schema)
        return True
    except jsonschema.exceptions.ValidationError:
        return False


[docs] def network_to_jsongraph(network, filename=''): r""" Write the network to disk as a JGF file. Parameters ---------- network : Network filename : str Desired file name, defaults to network name if not given """ # Ensure output file is valid filename = _parse_filename(filename=filename, ext='json') # Ensure network contains the required properties try: required_props = {'pore.diameter', 'pore.coords', 'throat.length', 'throat.conns', 'throat.diameter'} assert required_props.issubset(network.props()) except AssertionError: raise Exception('Error - network is missing one of: ' + str(required_props)) # Create 'metadata' JSON object graph_metadata_obj = {'number_of_nodes': network.Np, 'number_of_links': network.Nt} # Create 'nodes' JSON object nodes_obj = [ { 'id': str(ps), 'metadata': { 'node_squared_radius': int(network['pore.diameter'][ps] / 2)**2, 'node_coordinates': { 'x': int(network['pore.coords'][ps, 0]), 'y': int(network['pore.coords'][ps, 1]), 'z': int(network['pore.coords'][ps, 2]) } } } for ps in network.Ps] # Create 'edges' JSON object edges_obj = [ { 'id': str(ts), 'source': str(network['throat.conns'][ts, 0]), 'target': str(network['throat.conns'][ts, 1]), 'metadata': { 'link_length': float(network['throat.length'][ts]), 'link_squared_radius': float(network['throat.diameter'][ts] / 2)**2 } } for ts in network.Ts] # Build 'graph' JSON object from 'metadata', 'nodes' and 'edges' graph_obj = {'metadata': graph_metadata_obj, 'nodes': nodes_obj, 'edges': edges_obj} # Build full JSON object json_obj = {'graph': graph_obj} # Load and validate input JSON with open(filename, 'w') as file: json.dump(json_obj, file, indent=2)
[docs] def network_from_jsongraph(filename): r""" Loads the JGF file onto the given project. Parameters ---------- filename : str The name of the file containing the data to import. The formatting of this file is outlined below. Returns ------- network : dict An OpenPNM Network dictionary """ # Ensure input file is valid filename = _parse_filename(filename=filename, ext='json') # Load and validate input JSON with open(filename, 'r') as file: json_file = json.load(file) if not _validate_json(json_file): raise Exception('File is not in the JSON Graph Format') # Extract graph metadata from JSON number_of_nodes = json_file['graph']['metadata']['number_of_nodes'] number_of_links = json_file['graph']['metadata']['number_of_links'] # Extract node properties from JSON nodes = sorted(json_file['graph']['nodes'], key=lambda node: int(node['id'])) x = np.array([node['metadata']['node_coordinates']['x'] for node in nodes]) y = np.array([node['metadata']['node_coordinates']['y'] for node in nodes]) z = np.array([node['metadata']['node_coordinates']['z'] for node in nodes]) # Extract link properties from JSON edges = sorted(json_file['graph']['edges'], key=lambda edge: int(edge['id'])) source = np.array([int(edge['source']) for edge in edges]) target = np.array([int(edge['target']) for edge in edges]) link_length = np.array([edge['metadata']['link_length'] for edge in edges]) link_squared_radius = np.array( [edge['metadata']['link_squared_radius'] for edge in edges]) # Generate network object network = Network() network['pore.all'] = np.ones([number_of_nodes, ], dtype=bool) network['throat.all'] = np.ones([number_of_links, ], dtype=bool) # Define primitive throat properties network['throat.length'] = link_length network['throat.conns'] = np.column_stack([source, target]) network['throat.diameter'] = 2.0 * np.sqrt(link_squared_radius) # Define primitive pore properties network['pore.index'] = np.arange(number_of_nodes) network['pore.coords'] = np.column_stack([x, y, z]) network['pore.diameter'] = np.zeros(number_of_nodes) return network