Commit 7382da78 authored by Chris Cantwell's avatar Chris Cantwell
Browse files

Merge branch 'master' into fix/FileFunctionReading

parents 31650460 2b9f3512
......@@ -40,6 +40,7 @@ v4.4.0
- Fix bug in CMake Homebrew and MacPorts detection for OS X (!729)
- Fix bug in FieldUtils when using half mode expansions (!734)
- Do not read the same fld/pts files again for every variable (!670)
- Fix bug in CMake PETSc detection for Ubuntu 16.04/Debian 9 (!735)
**ADRSolver:**
- Add a projection equation system for C^0 projections (!675)
......@@ -58,11 +59,15 @@ v4.4.0
- Added a convective like outflow boundary condition from Dong (!713)
- Added the ability to specifiy Womersley boundary conditions for pulsatile flow (!472)
**CardiacEPSolver:**
- Added a Python translator utility to generate cell models from CellML (!723)
**FieldConvert:**
- Allow equi-spaced output for 1D and 2DH1D fields (!613)
- Update quality metric to include scaled Jacobian output (!695)
- Allow multiple XML files to be specified in InterpField module (!705)
- Fix issues with isocontour module (!719)
- Fix issue with interpolator routine (!746)
**NekMesh:**
- Modify curve module to allow for spline input (!628)
......@@ -108,6 +113,9 @@ v4.4.0
- Add module to add composite ID of elements as a field (!674)
- Add reader for Nek5000 field files (!680)
**Tester:**
- Fix output not displayed on segfault or system error (!745)
v4.3.5
------
**Library:**
......
......@@ -139,6 +139,8 @@ OPTION(NEKTAR_BUILD_PACKAGES "Build Nektar++ binary packages" OFF)
MARK_AS_ADVANCED(NEKTAR_BUILD_PACKAGES)
OPTION(NEKTAR_TEST_ALL "Include full set of regression tests to this build." OFF)
OPTION(NEKTAR_TEST_USE_HOSTFILE "Use a hostfile to explicitly specify number of
slots." OFF)
# Meshing utilities and library
IF (NOT WIN32)
......@@ -229,7 +231,6 @@ INCLUDE (ThirdPartyBoost)
INCLUDE (ThirdPartyFFTW)
INCLUDE (ThirdPartyArpack)
INCLUDE (ThirdPartyMPI)
INCLUDE (ThirdPartyPETSc)
INCLUDE (ThirdPartyVTK)
INCLUDE (ThirdPartySMV)
INCLUDE (ThirdPartyOCE)
......@@ -273,7 +274,7 @@ IF( NEKTAR_USE_WIN32_LAPACK )
ENDIF( NEKTAR_USE_WIN32_LAPACK )
IF( NEKTAR_USE_SYSTEM_BLAS_LAPACK )
INCLUDE(FindNativeBlasLapack)
INCLUDE(ThirdPartyBlasLapack)
SET(NEKTAR_USING_BLAS TRUE)
SET(NEKTAR_USING_LAPACK TRUE)
ENDIF( NEKTAR_USE_SYSTEM_BLAS_LAPACK )
......@@ -302,6 +303,8 @@ ELSE( NEKTAR_USE_MEMORY_POOLS )
REMOVE_DEFINITIONS(-DNEKTAR_MEMORY_POOL_ENABLED)
ENDIF( NEKTAR_USE_MEMORY_POOLS )
INCLUDE (ThirdPartyPETSc)
SET(Boost_USE_STATIC_LIBS OFF)
IF( WIN32 )
# The auto-linking feature has problems with USE_STATIC_LIBS off, so we use
......
......@@ -62,6 +62,7 @@ ENDIF ( MKL_LAPACK_FOUND )
SET( MKL_BLAS_INCLUDE_FILE ${MKL_INCLUDE_DIR}/mkl_blas.h )
SET( MKL_LAPACK_INCLUDE_FILE ${MKL_INCLUDE_DIR}/mkl_lapack.h )
GET_FILENAME_COMPONENT(MKL_LIB_DIR ${MKL_CORE} PATH)
IF (MKL_INCLUDE_DIR)
SET(MKL_FOUND ON)
......@@ -78,6 +79,7 @@ ELSE(MKL_FOUND OR MKL_INTEL_FOUND )
ENDIF (MKL_FOUND OR MKL_INTEL_FOUND )
MARK_AS_ADVANCED(MKL_INCLUDE_DIR)
MARK_AS_ADVANCED(MKL_LIB_DIR)
MARK_AS_ADVANCED(MKL_LAPACK)
MARK_AS_ADVANCED(MKL)
MARK_AS_ADVANCED(MKL_GUIDE)
......
......@@ -4,6 +4,8 @@ SET(NATIVE_BLAS_LAPACK_SEARCH_PATHS /usr/lib /usr/lib64 /usr/local/lib /usr/loca
FIND_LIBRARY(NATIVE_BLAS NAMES blas PATHS ${NATIVE_BLAS_LAPACK_SEARCH_PATHS})
FIND_LIBRARY(NATIVE_LAPACK NAMES lapack PATHS ${NATIVE_BLAS_LAPACK_SEARCH_PATHS})
GET_FILENAME_COMPONENT(NATIVE_BLAS_LIB_DIR ${NATIVE_BLAS} PATH)
GET_FILENAME_COMPONENT(NATIVE_LAPACK_LIB_DIR ${NATIVE_LAPACK} PATH)
IF (NATIVE_BLAS AND NATIVE_LAPACK)
......@@ -22,4 +24,6 @@ ENDIF (NATIVE_BLAS_LAPACK_FOUND)
MARK_AS_ADVANCED(NATIVE_BLAS)
MARK_AS_ADVANCED(NATIVE_LAPACK)
MARK_AS_ADVANCED(NATIVE_BLAS_LIB_DIR)
MARK_AS_ADVANCED(NATIVE_LAPACK_LIB_DIR)
......@@ -225,6 +225,13 @@ show :
else ()
set (PETSC_LIBRARY_VEC "NOTFOUND" CACHE INTERNAL "Cleared" FORCE) # There is no libpetscvec
petsc_find_library (SINGLE petsc)
# Debian 9/Ubuntu 16.04 uses _real and _complex extensions when using libraries in /usr/lib/petsc.
if (NOT PETSC_LIBRARY_SINGLE)
petsc_find_library (SINGLE petsc_real)
endif()
if (NOT PETSC_LIBRARY_SINGLE)
petsc_find_library (SINGLE petsc_complex)
endif()
foreach (pkg SYS VEC MAT DM KSP SNES TS ALL)
set (PETSC_LIBRARIES_${pkg} "${PETSC_LIBRARY_SINGLE}")
endforeach ()
......
########################################################################
#
# ThirdParty configuration for Nektar++
#
# BLAS/LAPACK
#
########################################################################
INCLUDE(FindNativeBlasLapack)
IF(NATIVE_BLAS_LAPACK_FOUND)
SET(BUILD_BLAS_LAPACK OFF)
ELSE()
IF(CMAKE_Fortran_COMPILER)
SET(BUILD_BLAS_LAPACK ON)
ELSE()
MESSAGE(SEND_ERROR "No blas installation or fortran compiler found")
ENDIF()
ENDIF()
OPTION(THIRDPARTY_BUILD_BLAS_LAPACK "Build blas and lapack libraries from ThirdParty."
${BUILD_BLAS_LAPACK})
IF(THIRDPARTY_BUILD_BLAS_LAPACK)
INCLUDE(ExternalProject)
EXTERNALPROJECT_ADD(
lapack-3.7.0
PREFIX ${TPSRC}
URL http://www.netlib.org/lapack/lapack-3.7.0.tgz
URL_MD5 "697bb8d67c7d336a0f339cc9dd0fa72f"
STAMP_DIR ${TPBUILD}/stamp
DOWNLOAD_DIR ${TPSRC}
SOURCE_DIR ${TPSRC}/lapack-3.7.0
BINARY_DIR ${TPBUILD}/lapack-3.7.0
TMP_DIR ${TPBUILD}/lapack-3.7.0-tmp
INSTALL_DIR ${TPDIST}
CONFIGURE_COMMAND ${CMAKE_COMMAND}
-G ${CMAKE_GENERATOR}
-DCMAKE_Fortran_COMPILER:FILEPATH=${CMAKE_Fortran_COMPILER}
-DCMAKE_INSTALL_PREFIX:PATH=${TPDIST}
-DCMAKE_INSTALL_LIBDIR:PATH=${TPDIST}/lib
-DBUILD_SHARED_LIBS:STRING=ON
-DBUILD_TESTING:STRING=OFF
${TPSRC}/lapack-3.7.0
)
SET(NATIVE_BLAS blas CACHE FILEPATH "BLAS library" FORCE)
SET(NATIVE_LAPACK lapack CACHE FILEPATH "LAPACK library" FORCE)
SET(NATIVE_BLAS_LIB_DIR ${TPDIST}/lib CACHE FILEPATH "BLAS library dir" FORCE)
SET(NATIVE_LAPACK_LIB_DIR ${TPDIST}/lib CACHE FILEPATH "LAPACK library dir" FORCE)
MARK_AS_ADVANCED(NATIVE_BLAS)
MARK_AS_ADVANCED(NATIVE_LAPACK)
MARK_AS_ADVANCED(NATIVE_BLAS_LIB_DIR)
MARK_AS_ADVANCED(NATIVE_LAPACK_LIB_DIR)
LINK_DIRECTORIES(${TPDIST}/lib)
INCLUDE_DIRECTORIES(${TPDIST}/include)
IF (WIN32)
MESSAGE(STATUS "Build blas: ${TPDIST}/${LIB_DIR}/${NATIVE_BLAS}.dll")
MESSAGE(STATUS "Build lapack: ${TPDIST}/${LIB_DIR}/${NATIVE_LAPACK}.dll")
ELSE ()
MESSAGE(STATUS "Build blas: ${TPDIST}/${LIB_DIR}/lib${NATIVE_BLAS}.a")
MESSAGE(STATUS "Build lapack: ${TPDIST}/${LIB_DIR}/${NATIVE_LAPACK}.a")
ENDIF()
ENDIF()
......@@ -49,6 +49,27 @@ IF (NEKTAR_USE_PETSC)
# we use a MUMPS build in ordering here, in the future it might make
# sense to hook it up with metis/scotch since this MIGHT be faster
SET(PETSC_MUMPS --download-scalapack --download-mumps)
SET(PETSC_DEPS "")
IF( NEKTAR_USE_BLAS_LAPACK )
IF( NEKTAR_USE_MKL AND MKL_FOUND )
SET(PETSC_MUMPS ${PETSC_MUMPS} --with-blas-lapack-dir=${MKL_LIB_DIR})
ELSEIF( NEKTAR_USE_WIN32_LAPACK )
SET(PETSC_MUMPS ${PETSC_MUMPS} --with-blas-lapack-dir=${LAPACK_DIR})
ELSEIF( NEKTAR_USE_SYSTEM_BLAS_LAPACK )
SET(PETSC_MUMPS ${PETSC_MUMPS} --with-blas-lapack-dir=${NATIVE_LAPACK_LIB_DIR})
IF(THIRDPARTY_BUILD_BLAS_LAPACK)
SET(PETSC_DEPS ${PETSC_DEPS} lapack-3.7.0)
ENDIF()
ELSE()
MESSAGE(STATUS "No suitable blas/lapack found, downloading")
SET(PETSC_MUMPS ${PETSC_MUMPS} --download-fblaslapack)
ENDIF()
ELSE()
MESSAGE(STATUS "No suitable blas/lapack found, downloading")
SET(PETSC_MUMPS ${PETSC_MUMPS} --download-fblaslapack)
ENDIF()
ELSE()
MESSAGE(WARNING "No Fortran support. Building PETSc without MUMPS support")
SET(PETSC_Fortran_COMPILER "0")
......@@ -56,6 +77,7 @@ IF (NEKTAR_USE_PETSC)
EXTERNALPROJECT_ADD(
petsc-3.7.2
DEPENDS ${PETSC_DEPS}
PREFIX ${TPSRC}
STAMP_DIR ${TPBUILD}/stamp
DOWNLOAD_DIR ${TPSRC}
......
......@@ -339,8 +339,7 @@ void Interpolator::Interpolate(
if (elmtid >= 0)
{
int offset = m_expInField[0]->GetPhys_Offset(
m_expInField[0]->GetOffset_Elmt_Id(elmtid));
int offset = m_expInField[0]->GetPhys_Offset(elmtid);
for (int f = 0; f < m_expInField.size(); ++f)
{
......@@ -424,8 +423,7 @@ void Interpolator::Interpolate(
if (elmtid >= 0)
{
int offset = m_expInField[0]->GetPhys_Offset(
m_expInField[0]->GetOffset_Elmt_Id(elmtid));
int offset = m_expInField[0]->GetPhys_Offset(elmtid);
for (int f = 0; f < m_expInField.size(); ++f)
{
......
......@@ -484,6 +484,7 @@ set(CPACK_SOURCE_IGNORE_FILES
"/library/Demos/LocalRegions/XmlFiles/"
"/solvers/ImageWarpingSolver/"
"/solvers/VortexWaveInteraction/"
"/solvers/CardiacEPSolver/Utilities/CellMLToNektar/"
"/solvers/IncNavierStokesSolver/Utilities/HybridPerformanceModel/"
"/utilities/Extras/"
)
......
......@@ -12,7 +12,7 @@
#include <iostream>
#include <string>
//#include <LibUtilities/BasicUtils/Vmath.hpp>
//#inc lude <LibUtilities/BasicUtils/Vmath.hpp>
#include <CardiacEPSolver/CellModels/LuoRudy91.h>
namespace Nektar
......
......@@ -60,7 +60,7 @@ std::string TenTusscher06::lookupIds[4] = {
std::string TenTusscher06::def =
LibUtilities::SessionReader::RegisterDefaultSolverInfo(
"CellModelVariant", "eEpicardium");
"CellModelVariant", "Epicardium");
/**
*
......
#!/usr/bin/env python
"""Copyright (c) 2005-2016, University of Oxford.
All rights reserved.
University of Oxford means the Chancellor, Masters and Scholars of the
University of Oxford, having an administrative office at Wellington
Square, Oxford OX1 2JD, UK.
This file is part of Chaste.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of the University of Oxford nor the names of its
contributors may be used to endorse or promote products derived from this
software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
"""
"""
This part of PyCml deals with converting CellML models into programming language code.
It is a thin executable wrapper around translators.py.
"""
import os #importing functions related to operating system
import sys #importing functions related to system (e.g. path directory etc)
# Make sure PyCml is on sys.path
pycml_path = os.path.dirname(os.path.realpath(__file__))
sys.path[0:0] = [pycml_path]
import translators #importing the main translator class
from translators import CellMLTranslator #again, just to make sure
import CellMLToNektarTranslator #importing the nektar sub-class
#This part actually runs the code
if __name__ == '__main__': #this part of the code is only run when CellMLToNektar.py is run directly, not imported
CellMLTranslator.register(CellMLTranslator, 'C++') #this registers the main translator and it's name when called as an option in modified_translators
CellMLTranslator.register(CellMLToNektarTranslator.CellMLToNektarTranslator, 'Nektar') #this registers the nektar subclass and it's name when called as an option in modified_translators
if '--profile' in sys.argv: #sys.argv is the list of command line items passed to the script, this checks if a specific translator is requested
import time, cProfile
profile_name = '/tmp/pycml-profile-%f-%d' % (time.time(), os.getpid())
cProfile.run('modified_translators.run()', profile_name) #the requested translator is run
else:
translators.run() #if no specific translator is requested, the default run function in modified_translators is run
#Below here seem to be variables that do some form of testing
# For use in testing
def euler(doc, t, nsteps=1000, dt=0.01):
global tvar, state_vars, exprs #assigns tvar, state_vars and exprs to be global variables, meaning they can be used by any function
tvar = t.free_vars[0] #takes the t-input and does "free_vars[0]" to it?
state_vars = t.state_vars #defines state_vars as the state_vars of the t-input?
for var in state_vars: #cycles through all the entries in "state_vars"
var.set_value(float(var.initial_value)) #for all the entries in "state_vars" it sets the value to a float of the initial value
tvar.set_value(0.0) #this sets the value of tvars to (0.0)?
exprs = [e for e in doc.model.get_assignments() #I don't understand this part
if isinstance(e, modified_translators.mathml_apply)] #what is the mathml_apply function? Can't find it in modified_translators
for _ in range(nsteps): #this is a for-loop through all the values up to the input of nsteps
for expr in exprs: #this cycles through all the entries in exprs
expr.evaluate()
tvar.set_value(tvar.get_value() + dt)
for var in state_vars:
var.set_value(var.get_value() +
dt * var.get_value(ode=tvar))
return
def writefile(doc, outfn='test.cml'):
# Write out CellML file
st = modified_translators.open_output_stream(outfn)
doc.xml(indent=1, stream=st)
st.close()
return
def show_usage(doc):
for comp in doc.model.component:
for var in comp.variable:
print var.fullname(), var._cml_usage_count
def fix_divide_by_zero(doc):
"""
Several models have equations of a form that may give rise to
a divide by zero error on simulation, especially when lookup
tables are used. The general form is:
(a * (V - v0)) / (exp(b * (V - v0)) - 1)
When V = v0 this is undefined, however the limit of the
function as V approaches v0 from either side is well-defined,
and each limit is the same. We approximate the limit by
linear interpolation between values of the expression for
(V-v0) = +/- 1e-10.
"""
divides = [d.xml_parent
for d in doc.xml_xpath(u'//m:apply/m:divide')]
for divide in divides:
pass
return
This diff is collapsed.
"""Copyright (c) 2005-2016, University of Oxford.
All rights reserved.
University of Oxford means the Chancellor, Masters and Scholars of the
University of Oxford, having an administrative office at Wellington
Square, Oxford OX1 2JD, UK.
This file is part of Chaste.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of the University of Oxford nor the names of its
contributors may be used to endorse or promote products derived from this
software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
"""
"""
This module abstracts the interface to RDF metadata about CellML models.
The RdfProcessor class below pretends to be the module itself, so all its properties
are available at module-level, and these should typically be called by users.
It also provides sets METADATA_NAMES and STIMULUS_NAMES, which contain the local names
of terms in the ontology that can annotate variables, and the subset of those names
which define properties of the stimulus current (but not the current itself), respectively.
"""
import logging
import os
import sys
import types
from cStringIO import StringIO
# We now only support rdflib for RDF processing
import rdflib
def __init__(module):
# Import pycml here, to avoid circular import surprises
import pycml
module.pycml = pycml
class RdfProcessor(object):
"""Implements CellML metadata functionality using the RDFLib library."""
def __init__(self, name):
"""Create the wrapper."""
# Magic for pretending to be a module
self._module = sys.modules[name]
sys.modules[name] = self
self._initializing = True
# Map from cellml_model instances to RDF stores
self._models = {}
# Oxford metadata will be loaded lazily
self._metadata_names = self._stimulus_names = None
# Cope with differences in API between library versions
rdflib_major_version = int(rdflib.__version__[0])
if rdflib_major_version >= 3:
self.Graph = rdflib.Graph
else:
self.Graph = rdflib.ConjunctiveGraph
def __getattribute__(self, name):
"""Provide access to real module-level variables as though they're class properties."""
# call module.__init__ after import introspection is done
baseget = super(RdfProcessor, self).__getattribute__
module = baseget('_module')
if baseget('_initializing') and not name[:2] == '__' == name[-2:]:
setattr(self, '_initializing', False)
__init__(module)
try:
return baseget(name)
except AttributeError:
return getattr(module, name)
def _debug(*args):
pycml.DEBUG('cellml-metadata', *args)
def _load_ontology(self):
"""Load the Oxford metadata ontology the first time it's needed."""
pycml_path = os.path.dirname(os.path.realpath(__file__))
oxmeta_ttl = os.path.join(pycml_path, 'oxford-metadata.ttl')
oxmeta_rdf = os.path.join(pycml_path, 'oxford-metadata.rdf')
g = self.Graph()
# We allow a difference in modification time of 10s, so we don't get confused when checking out!
if os.stat(oxmeta_ttl).st_mtime > os.stat(oxmeta_rdf).st_mtime + 10.0:
# Try to regenerate RDF/XML version of ontology
try:
g.parse(oxmeta_ttl, format='turtle')
except Exception, e:
print >> sys.stderr, 'Unable to convert metadata from Turtle format to RDF/XML.'
print >> sys.stderr, 'Probably you need to upgrade rdflib to version 4.\nDetails of error:'
raise
g.serialize(oxmeta_rdf, format='xml')
else:
# Just parse the RDF/XML version
g.parse(oxmeta_rdf, format='xml')
annotation_terms = list(g.subjects(rdflib.RDF.type, rdflib.URIRef(pycml.NSS['oxmeta']+u'Annotation')))
self._metadata_names = frozenset(map(lambda node: self.namespace_member(node, pycml.NSS['oxmeta']), annotation_terms))
# Parameters for the stimulus current
self._stimulus_names = frozenset(filter(lambda name: name.startswith('membrane_stimulus_current_'), self._metadata_names))
@property
def METADATA_NAMES(self):
"""Fake a module-level constant as a property for lazy loading."""
if self._metadata_names is None:
self._load_ontology()
return self._metadata_names
@property
def STIMULUS_NAMES(self):
"""Fake a module-level constant as a property for lazy loading."""
if self._stimulus_names is None:
self._load_ontology()
return self._stimulus_names
def _create_new_store(self, cellml_model):
"""Create a new RDF store for the given CellML model.
The new store will be available as self._models[cellml_model].
"""
self._models[cellml_model] = self.Graph()
def _add_rdf_element(self, cellml_model, rdf_text):
"""Add statements to the model's graph from the given serialized RDF."""
g = self.Graph()
g.parse(StringIO(rdf_text))
rdf_model = self._models[cellml_model]
for stmt in g:
rdf_model.add(stmt)
def _serialize(self, cellml_model):
"""Serialize the RDF model for this CellML model to XML."""
return self._models[cellml_model].serialize()
def get_rdf_from_model(self, cellml_model):
"""Get the RDF graph of the given CellML model.
If this model is already in our map, return the existing RDF store.
Otherwise, extract metadata from all RDF elements in the cellml_model,
create a new RDF graph from these, and delete the original elements.
"""
if not cellml_model in self._models:
rdf_blocks = cellml_model.xml_xpath(u'//rdf:RDF')
self._create_new_store(cellml_model)
for rdf_block in rdf_blocks:
rdf_text = rdf_block.xml()
self._add_rdf_element(cellml_model, rdf_text)
rdf_block.xml_parent.xml_remove_child(rdf_block)
return self._models[cellml_model]
def remove_model(self, cellml_model):
"""The given model is being deleted / no longer needed."""
if cellml_model in self._models:
del self._models[cellml_model]
self._debug('Clearing RDF state for model', cellml_model.name)
def update_serialized_rdf(self, cellml_model):
"""Ensure the RDF serialized into the given CellML model is up-to-date.
If we have done any metadata processing on the given model, will serialize
our RDF store into the rdf:RDF element child of the model.
"""
if cellml_model in self._models:
# Paranoia: ensure it doesn't already contain serialized RDF
rdf_blocks = cellml_model.xml_xpath(u'//rdf:RDF')
if rdf_blocks:
pycml.LOG('cellml-metadata', logging.WARNING, 'Removing existing RDF in model.')
for rdf_block in rdf_blocks:
rdf_block.xml_parent.xml_remove_child(rdf_block)
# Serialize the RDF model into cellml_model.RDF
rdf_text = self._serialize(cellml_model)
rdf_doc = pycml.amara.parse(rdf_text)
cellml_model.xml_append(rdf_doc.RDF)
# Remove the RDF model
self.remove_model(cellml_model)
def create_rdf_node(self, node_content=None, fragment_id=None):
"""Create an RDF node.
node_content, if given, must either be a tuple (qname, namespace_uri),
or a string, in which case it is interpreted as a literal RDF node.
Alternatively, fragment_id may be given to refer to a cmeta:id within the
current model.
If neither are given, a blank node is created.
"""
if fragment_id:
node = rdflib.URIRef(str('#'+fragment_id))