Viewing file: Triclops.py (14.5 KB) -rw-r--r-- Select action/file-type: (+) | (+) | (+) | Code (+) | Session (+) | (+) | SDB (+) | (+) | (+) | (+) | (+) | (+) |
#!/usr/local/bin/python import urllib import os import re import sys import codecs import tempfile from xml.dom import Node
from Ft.Rdf import RDF_SCHEMA_BASE, RDF_MS_BASE,OBJECT_TYPE_RESOURCE, OWL_NS from Ft.Rdf._4rdf import CheckLabel from Ft.Xml import XPath from string import *
def ParseNsMappings(nsMappings, nsDict={}, mappingUri=None): if type(nsMappings) == type('') or type(nsMappings) == type(u''): #parsing from text from Ft.Xml.Domlette import NonvalidatingReader mappingsNode = NonvalidatingReader.parseString(nsMappings.encode('utf-8'), mappingUri) elif isinstance(nsMappings, node): #parsing from node mappingsNode = nsMappings else: return {} nsDict.update({'fres':'http://xmlns.4suite.org/reserved'})
mappingsContext = XPath.Context.Context(mappingsNode, processorNss=nsDict)
_mappingElements = XPath.Compile('/fres:NsMappings/fres:NsMapping') _mappingPrefixExpression = XPath.Compile('string(Prefix)') _mappingUriExpression = XPath.Compile('string(Uri)')
mappings={} for nsMapping in _mappingElements.evaluate(mappingsContext): if nsMapping.localName == u"NsMapping": mappingsContext.node = nsMapping prefix=_mappingPrefixExpression.evaluate(mappingsContext) uri =_mappingUriExpression.evaluate(mappingsContext) #print "parsed out %s -> %s from user ns mapping"%(prefix,uri) mappings[prefix]=uri elif nsMapping.localName == u"Merge": href = nsMapping.attributes.get((None, u"href")) ParseNsMappings(href, nsDict=mappings) #Go recursive
return mappings
RECTANGLE_PATTERN = re.compile(r'rectangle\s+\([\d]+,[\d]+\)\s+\([\d]+,[\d]+\)\s+[^\s]+.*')
class RDFGraphVizEngine: def __init__(self, gvisDir, mapName='rdfImageMap', uriFormat='%s', maxArcs=None, outputJpeg=None,useNeato=False): """ """ self._useNeato = useNeato self.maxArcs = int(self._useNeato and 160 or 300) self.mapName = mapName self.uriFormat = uriFormat or '%s' self.gviz = gvisDir.strip() if outputJpeg: self.outputJpeg = outputJpeg self.outputSvg = outputJpeg[:outputJpeg.find('.')] + '.svg' #print self.outputSvg else: self.outputJpeg = tempfile.mktemp('.jpg') self.outputSvg = tempfile.mktemp('.svg') #print self.outputSvg #self.tmp = tempDir.strip() # = or os.path.join(self.tmp, 'output.jpg') dotPath = os.path.join(self.gviz, 'dot') winDotPath = os.path.join(self.gviz, 'dot.exe') if not os.path.exists(dotPath) and not os.path.exists(winDotPath): raise Exception("graphViz is not properly setup or not installed (cannot locate 'dot' executable at %s or %s)"%(str(dotPath),str(winDotPath))) #print "setting up RDFGraphVizEngine. Gvis dir is %s, uriFormat is %s, and tmp dir is at %s"%(self.gviz, self.uriFormat, self.tmp) #print "setting up RDFGraphVizEngine. Gvis dir is %s, uriFormat is %s"%(self.gviz, self.uriFormat)
def retrieveResourceUris(self, resultNode): resoureExpression = Compile('//Resource') def resourceExists(self, name, model): """ Checks model.complete(model,None,None) to determine if name exists """ try: stmts=model.complete(name, None, None) except: return [] else: return stmts
def resourceViewer(self, model, resourceUri=None, scoped=0, rotate=0, splitpreds=1, resultTxt=None, nsDict=None, resultsNode=None): nsDict = nsDict or {} #print nsDict singleResource = '' color='' if resultTxt or resultsNode: color = 'color=red' stmts = []
if resultTxt: from Ft.Xml.Domlette import NonvalidatingReader # FIXME: Find a better way to detect null results, perhaps from # raw Versa data. Otherwise we should be passing through # exceptions. try: resultsNode = NonvalidatingReader.parseString( resultTxt.encode('utf-8'), 'http://4Suite.org') except: return "No resources to view"
from Ft.Xml import XPath resultsContext = XPath.Context.Context(resultsNode)
_resourceExpr = XPath.Compile('//Resource/text() | //BlankNode/text()') evaluated = _resourceExpr.evaluate(resultsContext) if len(evaluated) == 1: singleResource = evaluated[0].nodeValue for res in evaluated: res = res.nodeValue if len(res.split('ftss:///')) > 1: res = '/' + res.split('ftss:///')[-1] #print "adding *all* statements about %s to graph"%(res) #print "Adding statements about %s to graph"%(res) stmts_in_scope = [] if stmts_in_scope and scoped: #To avoid duplicate statements in cases of rdf:about="" stmts.extend(stmts_in_scope) else: stmts.extend(model.complete(res, '', '')) stmts.extend(model.complete('', '', res)) else: if scoped: color='' stmts = model.complete('', '', '', scope=resourceUri) or model.complete('', '', '', scope=resourceUri) else: stmts=model.complete('', '', '')
rotate = rotate and 'rotate=90' or 'rotate=180' if self._useNeato: output = 'digraph G {overlap=scale;splines=true;center=true;orientation=land;resolution=0.96;rankdir=LR;ratio=fill;%s\n'%(rotate) else: output = 'digraph G {center=true;orientation=land;resolution=0.96;rankdir=LR;ratio=fill;%s\n'%(rotate)
formatDict={} arcs = len(stmts) if arcs > self.maxArcs: raise "Attempt to process %s arcs. This is beyond the recommended (%s) threshold of raphviz's capabilities and size constraints"%(arcs,self.maxArcs) for stmt in stmts: kv = [(stmt.predicate, stmt.object, stmt.objectType)] currentKv = formatDict.get(stmt.subject, []) formatDict[stmt.subject] = currentKv + kv
index = 0 unknownIndex = len(formatDict.keys()) for resName, resourceArcs in formatDict.items(): if model.isBnodeLabel(resName): #See if it has an rdf:type statement associated with it. Use if so type_stmts = model.complete(resName, RDF_MS_BASE+"type", None) if type_stmts: type_str = splitPredicate(type_stmts[0].object,nsDict) rdfClass=CheckLabel(model,type_str) l = "Anonymous\\n%s"%(rdfClass) else: l = CheckLabel(model,resName) output = output+'\t%s [label = "%s",URL="%s"]\n'%(index, l, self.uriFormat%(urllib.quote(resName))) else: output = output+'\t%s [label = "%s",URL="%s" %s]\n'%(index, ResourceName(model, resName,nsDict), self.uriFormat%(urllib.quote(resName)), color) for predicate, object, otype in resourceArcs: if predicate in [RDF_MS_BASE+"type",RDF_SCHEMA_BASE+'label']: continue objUri = object if splitpreds: predicate = splitPredicate(predicate, nsDict) if object in formatDict.keys(): object = formatDict.keys().index(object) else: exists = self.resourceExists(object, model) isLiteralbyOntology = model.complete(predicate,RDF_MS_BASE+'type',OWL_NS+'DatatypeProperty') isResource = (otype == OBJECT_TYPE_RESOURCE) if isResource and not isLiteralbyOntology: resUri = object if exists: output = output + '\t%s [label = "%s",URL="%s" %s]\n'%(unknownIndex, ResourceName(model, objUri,nsDict).replace('"', "'"), self.uriFormat%(urllib.quote(object)), color) else: output = output + '\t%s [label = "%s"]\n'%(unknownIndex, ResourceName(model, objUri,nsDict).replace('"', "'")) else: output = output + '\t%s [label = "%s", shape=box]\n'%(unknownIndex, ResourceName(model, objUri,nsDict).replace('"', "'")) object = unknownIndex unknownIndex += 1
output = output + '\t%s -> %s [label = "%s"];\n'%(index, object, predicate) index = index + 1
output = output + "}"
outputDot = tempfile.mktemp('.dot') outputMap = tempfile.mktemp('.map') dotExecPath = os.path.join(self.gviz, self._useNeato and 'neato' or 'dot') dotfile = codecs.open(outputDot, 'w', 'utf-8') dotfile.write(output) dotfile.close()
# dot -Tismap output.dot -o output.map args = [os.path.basename(dotExecPath), '-Tismap', outputDot, '-o', outputMap] os.spawnv(os.P_WAIT, dotExecPath, args) # dot -Tjpeg output.dot -o output.jpg args = [os.path.basename(dotExecPath), '-Tjpeg', outputDot, '-o', self.outputJpeg] os.spawnv(os.P_WAIT, dotExecPath, args) # dot -Tsvg output.dot -o output.svg args = [os.path.basename(dotExecPath), '-Tsvg', outputDot, '-o', self.outputSvg] os.spawnv(os.P_WAIT, dotExecPath, args) if not(os.path.exists(self.outputSvg)): raise Exception("%s wasn't created! arg list used: %s"%(self.svgPath,args)) from Ft.Xml.Domlette import NonvalidatingReader from Ft.Xml import XPath from Ft.Xml.Lib.Print import PrettyPrint from cStringIO import StringIO stream = StringIO() doc = NonvalidatingReader.parseUri('file://'+self.outputSvg) xContext=XPath.Context.Context(doc,processorNss={'svg':'http://www.w3.org/2000/svg'}) w=float(split(XPath.Compile('/svg:svg/@width').evaluate(xContext)[0].nodeValue,'p')[0]) h=float(split(XPath.Compile('/svg:svg/@height').evaluate(xContext)[0].nodeValue,'p')[0]) scaleFactor = min(1,2048 / w) self.svgHeight = h * scaleFactor self.svgWidth = w * scaleFactor g = XPath.Compile('/svg:svg/svg:g').evaluate(xContext)[0] svgRoot = XPath.Compile('/svg:svg').evaluate(xContext)[0]
#svgRoot.setAttributeNS(None,'width','100%') #svgRoot.setAttributeNS(None,'height','100%') svgRoot.removeAttributeNS(None,'viewBox') g.setAttributeNS(None,'transform','scale(%s)'%(scaleFactor)) PrettyPrint(doc,stream) svgfile = codecs.open(self.outputSvg, 'w', 'utf-8') svgfile.write(stream.getvalue()) svgfile.close()
mapfile = codecs.open(outputMap, 'r', 'utf-8') mapfile_content = mapfile.read() mapfile.close() matches = RECTANGLE_PATTERN.findall(mapfile_content)
rt = '<MAP name="%s">\n'%(self.mapName) for match in matches: splitString = match.split(' ') corner1x, corner1y = splitString[1][1:-1].split(',') corner2x, corner2y = splitString[2][1:-1].split(',') resourceUri = splitString[3] rt = rt+'<AREA href="%s" shape="rect" coords="%s,%s,%s,%s"/>\n'%(resourceUri, corner1x, corner2y, corner2x, corner1y) rt = rt + '</MAP>' return rt def splitPredicate(predicate, nsDict): reverseDict={} for key, value in nsDict.items(): reverseDict[value]=key splitPred=predicate.split('#') uri='' local=predicate if len(splitPred)>1: local = splitPred[-1] if len(splitPred)>2: uri = '#'.join(splitPred[0:-2]) else: uri = splitPred[0] uri = uri + '#' elif len(predicate.split('/'))>1: if predicate[-1] =='/': local=predicate prefix='' else: local = predicate.split('/')[-1] uri = '/'.join(predicate.split('/')[0:-2]) + '/' prefix = '' if reverseDict.has_key(uri): prefix = reverseDict[uri] + ':' return prefix + local def ResourceName(model, resourceUri,nsDict): #Should also account for rdf:type as well as rdfs:label label_stmts = model.complete(resourceUri, RDF_SCHEMA_BASE+"label", None) type_stmts = model.complete(resourceUri, RDF_MS_BASE+"type", None) if label_stmts: return "<%s>"%label_stmts[0].object elif type_stmts: type_str = splitPredicate(type_stmts[0].object,nsDict) rdfClass=CheckLabel(model,type_str) if rdfClass == type_str: rdfClass = splitPredicate(type_str,nsDict).replace('\n','\\n') label = splitPredicate(resourceUri,nsDict).replace('\n','\\n') return "%s\\n{%s}"%(label,rdfClass) else: return splitPredicate(resourceUri,nsDict).replace('\n','\\n')
if __name__ == '__main__': from Ft.Rdf import Model from Ft.Rdf.Drivers import Memory from Ft.Rdf.Serializers.Dom import Serializer from Ft.Xml.Domlette import NonvalidatingReader
if len(sys.argv)<5: print "usage: RDFVisualizer.py graphVizBinDir rdfModel output\n" print "graphVizBinDir - the 'bin' directory of graphvis" print "rdfModel - the file containing the RDF serialization to graph" print "output - the name of the file to write the jpeg image to" sys.exit(0)
tmpDir = sys.argv[1] gvisBin = sys.argv[2] modelFile = sys.argv[3] output = sys.argv[4] print "%s -> %s"%(modelFile, output) doc = NonvalidatingReader.parseUri(urllib.pathname2url(modelFile))
d = Memory.DbAdapter('') d.begin() model = Model.Model(d) szr = Serializer() szr.deserialize(model, doc, 'versaExample') gvizAgent=RDFGraphVizEngine(gvisDir=gvisBin, outputJpeg=output) gvizAgent.resourceViewer(model, scoped=1)
|