Mercurial > code > home > repos > homeauto
annotate service/reasoning/inputgraph.py @ 1117:d5687ba23279
fix input graph web display by dirtying combinedGraph better.
Ignore-this: e40e7499e3d675b029f829a1f269b83a
darcs-hash:c15a1820ca7b5e40b2a27946bfe1c87cc80612fa
author | drewp <drewp@bigasterisk.com> |
---|---|
date | Sun, 09 Oct 2016 13:57:50 -0700 |
parents | 8caf62030955 |
children | c51075f267bc |
rev | line source |
---|---|
1108
8caf62030955
reasoning uses sse_collector
drewp <drewp@bigasterisk.com>
parents:
1086
diff
changeset
|
1 import logging, time, sys |
1080 | 2 |
3 from rdflib import Graph, ConjunctiveGraph | |
1108
8caf62030955
reasoning uses sse_collector
drewp <drewp@bigasterisk.com>
parents:
1086
diff
changeset
|
4 from rdflib import Namespace, URIRef, Literal, RDF, RDFS |
1086 | 5 from rdflib.parser import StringInputSource |
1080 | 6 |
7 from twisted.python.filepath import FilePath | |
8 from twisted.internet.defer import inlineCallbacks, gatherResults | |
9 | |
10 from rdflibtrig import addTrig | |
11 from graphop import graphEqual | |
12 | |
1108
8caf62030955
reasoning uses sse_collector
drewp <drewp@bigasterisk.com>
parents:
1086
diff
changeset
|
13 from patchsource import ReconnectingPatchSource |
8caf62030955
reasoning uses sse_collector
drewp <drewp@bigasterisk.com>
parents:
1086
diff
changeset
|
14 |
8caf62030955
reasoning uses sse_collector
drewp <drewp@bigasterisk.com>
parents:
1086
diff
changeset
|
15 sys.path.append("/my/proj/light9") |
8caf62030955
reasoning uses sse_collector
drewp <drewp@bigasterisk.com>
parents:
1086
diff
changeset
|
16 from light9.rdfdb.rdflibpatch import patchQuads |
8caf62030955
reasoning uses sse_collector
drewp <drewp@bigasterisk.com>
parents:
1086
diff
changeset
|
17 |
1080 | 18 log = logging.getLogger('fetch') |
19 | |
20 ROOM = Namespace("http://projects.bigasterisk.com/room/") | |
21 DEV = Namespace("http://projects.bigasterisk.com/device/") | |
22 | |
23 | |
1086 | 24 def parseRdf(text, contentType): |
25 g = Graph() | |
26 g.parse(StringInputSource(text), format={ | |
27 'text/n3': 'n3', | |
28 }[contentType]) | |
29 return g | |
30 | |
31 | |
1108
8caf62030955
reasoning uses sse_collector
drewp <drewp@bigasterisk.com>
parents:
1086
diff
changeset
|
32 class RemoteData(object): |
8caf62030955
reasoning uses sse_collector
drewp <drewp@bigasterisk.com>
parents:
1086
diff
changeset
|
33 def __init__(self, onChange): |
8caf62030955
reasoning uses sse_collector
drewp <drewp@bigasterisk.com>
parents:
1086
diff
changeset
|
34 self.onChange = onChange |
8caf62030955
reasoning uses sse_collector
drewp <drewp@bigasterisk.com>
parents:
1086
diff
changeset
|
35 self.graph = ConjunctiveGraph() |
8caf62030955
reasoning uses sse_collector
drewp <drewp@bigasterisk.com>
parents:
1086
diff
changeset
|
36 self.patchSource = ReconnectingPatchSource(URIRef('http://bang:9072/graph/home'), self.onPatch) |
8caf62030955
reasoning uses sse_collector
drewp <drewp@bigasterisk.com>
parents:
1086
diff
changeset
|
37 |
8caf62030955
reasoning uses sse_collector
drewp <drewp@bigasterisk.com>
parents:
1086
diff
changeset
|
38 def onPatch(self, p, fullGraph): |
8caf62030955
reasoning uses sse_collector
drewp <drewp@bigasterisk.com>
parents:
1086
diff
changeset
|
39 if fullGraph: |
8caf62030955
reasoning uses sse_collector
drewp <drewp@bigasterisk.com>
parents:
1086
diff
changeset
|
40 self.graph = ConjunctiveGraph() |
8caf62030955
reasoning uses sse_collector
drewp <drewp@bigasterisk.com>
parents:
1086
diff
changeset
|
41 patchQuads(self.graph, |
8caf62030955
reasoning uses sse_collector
drewp <drewp@bigasterisk.com>
parents:
1086
diff
changeset
|
42 deleteQuads=p.delQuads, |
8caf62030955
reasoning uses sse_collector
drewp <drewp@bigasterisk.com>
parents:
1086
diff
changeset
|
43 addQuads=p.addQuads, |
8caf62030955
reasoning uses sse_collector
drewp <drewp@bigasterisk.com>
parents:
1086
diff
changeset
|
44 perfect=True) |
8caf62030955
reasoning uses sse_collector
drewp <drewp@bigasterisk.com>
parents:
1086
diff
changeset
|
45 |
8caf62030955
reasoning uses sse_collector
drewp <drewp@bigasterisk.com>
parents:
1086
diff
changeset
|
46 ignorePredicates = [ |
8caf62030955
reasoning uses sse_collector
drewp <drewp@bigasterisk.com>
parents:
1086
diff
changeset
|
47 ROOM['signalStrength'], |
8caf62030955
reasoning uses sse_collector
drewp <drewp@bigasterisk.com>
parents:
1086
diff
changeset
|
48 # perhaps anything with a number-datatype for its |
8caf62030955
reasoning uses sse_collector
drewp <drewp@bigasterisk.com>
parents:
1086
diff
changeset
|
49 # object should be filtered out, and you have to make |
8caf62030955
reasoning uses sse_collector
drewp <drewp@bigasterisk.com>
parents:
1086
diff
changeset
|
50 # an upstream quantization (e.g. 'temp high'/'temp |
8caf62030955
reasoning uses sse_collector
drewp <drewp@bigasterisk.com>
parents:
1086
diff
changeset
|
51 # low') if you want to do reasoning on the difference |
8caf62030955
reasoning uses sse_collector
drewp <drewp@bigasterisk.com>
parents:
1086
diff
changeset
|
52 URIRef("http://bigasterisk.com/map#lastSeenAgoSec"), |
8caf62030955
reasoning uses sse_collector
drewp <drewp@bigasterisk.com>
parents:
1086
diff
changeset
|
53 URIRef("http://bigasterisk.com/map#lastSeenAgo"), |
8caf62030955
reasoning uses sse_collector
drewp <drewp@bigasterisk.com>
parents:
1086
diff
changeset
|
54 ROOM['usingPower'], |
8caf62030955
reasoning uses sse_collector
drewp <drewp@bigasterisk.com>
parents:
1086
diff
changeset
|
55 ROOM['idleTimeMinutes'], |
8caf62030955
reasoning uses sse_collector
drewp <drewp@bigasterisk.com>
parents:
1086
diff
changeset
|
56 ROOM['idleTimeMs'], |
8caf62030955
reasoning uses sse_collector
drewp <drewp@bigasterisk.com>
parents:
1086
diff
changeset
|
57 ROOM['graphLoadMs'], |
8caf62030955
reasoning uses sse_collector
drewp <drewp@bigasterisk.com>
parents:
1086
diff
changeset
|
58 ROOM['localTimeToSecond'], |
8caf62030955
reasoning uses sse_collector
drewp <drewp@bigasterisk.com>
parents:
1086
diff
changeset
|
59 ROOM['history'], |
8caf62030955
reasoning uses sse_collector
drewp <drewp@bigasterisk.com>
parents:
1086
diff
changeset
|
60 ROOM['temperatureF'], |
8caf62030955
reasoning uses sse_collector
drewp <drewp@bigasterisk.com>
parents:
1086
diff
changeset
|
61 ROOM['connectedAgo'], |
8caf62030955
reasoning uses sse_collector
drewp <drewp@bigasterisk.com>
parents:
1086
diff
changeset
|
62 RDFS['comment'], |
8caf62030955
reasoning uses sse_collector
drewp <drewp@bigasterisk.com>
parents:
1086
diff
changeset
|
63 ] |
8caf62030955
reasoning uses sse_collector
drewp <drewp@bigasterisk.com>
parents:
1086
diff
changeset
|
64 ignoreContexts = [ |
8caf62030955
reasoning uses sse_collector
drewp <drewp@bigasterisk.com>
parents:
1086
diff
changeset
|
65 URIRef('http://bigasterisk.com/sse_collector/'), |
8caf62030955
reasoning uses sse_collector
drewp <drewp@bigasterisk.com>
parents:
1086
diff
changeset
|
66 ] |
8caf62030955
reasoning uses sse_collector
drewp <drewp@bigasterisk.com>
parents:
1086
diff
changeset
|
67 for affected in p.addQuads + p.delQuads: |
8caf62030955
reasoning uses sse_collector
drewp <drewp@bigasterisk.com>
parents:
1086
diff
changeset
|
68 if (affected[1] not in ignorePredicates and |
8caf62030955
reasoning uses sse_collector
drewp <drewp@bigasterisk.com>
parents:
1086
diff
changeset
|
69 affected[3] not in ignoreContexts): |
8caf62030955
reasoning uses sse_collector
drewp <drewp@bigasterisk.com>
parents:
1086
diff
changeset
|
70 log.debug(" remote graph changed") |
8caf62030955
reasoning uses sse_collector
drewp <drewp@bigasterisk.com>
parents:
1086
diff
changeset
|
71 self.onChange() |
8caf62030955
reasoning uses sse_collector
drewp <drewp@bigasterisk.com>
parents:
1086
diff
changeset
|
72 break |
8caf62030955
reasoning uses sse_collector
drewp <drewp@bigasterisk.com>
parents:
1086
diff
changeset
|
73 else: |
8caf62030955
reasoning uses sse_collector
drewp <drewp@bigasterisk.com>
parents:
1086
diff
changeset
|
74 log.debug(" remote graph has no changes to trigger rules") |
8caf62030955
reasoning uses sse_collector
drewp <drewp@bigasterisk.com>
parents:
1086
diff
changeset
|
75 |
1080 | 76 class InputGraph(object): |
1108
8caf62030955
reasoning uses sse_collector
drewp <drewp@bigasterisk.com>
parents:
1086
diff
changeset
|
77 def __init__(self, inputDirs, onChange): |
1080 | 78 """ |
79 this has one Graph that's made of: | |
80 - all .n3 files from inputDirs (read at startup) | |
81 - all the remote graphs, specified in the file graphs | |
82 | |
83 call updateFileData or updateRemoteData to reread those | |
84 graphs. getGraph to access the combined graph. | |
85 | |
86 onChange(self) is called if the contents of the full graph | |
87 change (in an interesting way) during updateFileData or | |
88 updateRemoteData. Interesting means statements other than the | |
89 ones with the predicates on the boring list. onChange(self, | |
90 oneShot=True) means: don't store the result of this change | |
91 anywhere; it needs to be processed only once | |
92 """ | |
93 self.inputDirs = inputDirs | |
1117
d5687ba23279
fix input graph web display by dirtying combinedGraph better.
drewp <drewp@bigasterisk.com>
parents:
1108
diff
changeset
|
94 self._onChange = onChange |
1080 | 95 self._fileGraph = Graph() |
1117
d5687ba23279
fix input graph web display by dirtying combinedGraph better.
drewp <drewp@bigasterisk.com>
parents:
1108
diff
changeset
|
96 self._remoteData = RemoteData(lambda: self.onChangeLocal()) |
1080 | 97 self._combinedGraph = None |
98 self._oneShotAdditionGraph = None | |
99 | |
1117
d5687ba23279
fix input graph web display by dirtying combinedGraph better.
drewp <drewp@bigasterisk.com>
parents:
1108
diff
changeset
|
100 def onChangeLocal(self, oneShot=False, oneShotGraph=None): |
d5687ba23279
fix input graph web display by dirtying combinedGraph better.
drewp <drewp@bigasterisk.com>
parents:
1108
diff
changeset
|
101 self._combinedGraph = None |
d5687ba23279
fix input graph web display by dirtying combinedGraph better.
drewp <drewp@bigasterisk.com>
parents:
1108
diff
changeset
|
102 self._onChange(self, oneShot=oneShot, oneShotGraph=oneShotGraph) |
d5687ba23279
fix input graph web display by dirtying combinedGraph better.
drewp <drewp@bigasterisk.com>
parents:
1108
diff
changeset
|
103 |
1080 | 104 def updateFileData(self): |
105 """ | |
106 make sure we contain the correct data from the files in inputDirs | |
107 """ | |
108 # this sample one is actually only needed for the output, but I don't | |
109 # think I want to have a separate graph for the output | |
110 # handling | |
111 log.debug("read file graphs") | |
112 for fp in FilePath("input").walk(): | |
113 if fp.isdir(): | |
114 continue | |
115 if fp.splitext()[1] != '.n3': | |
116 continue | |
117 log.debug("read %s", fp) | |
118 # todo: if this fails, leave the report in the graph | |
119 self._fileGraph.parse(fp.open(), format="n3") | |
120 self._combinedGraph = None | |
121 | |
1117
d5687ba23279
fix input graph web display by dirtying combinedGraph better.
drewp <drewp@bigasterisk.com>
parents:
1108
diff
changeset
|
122 self.onChangeLocal() |
1080 | 123 |
124 def addOneShot(self, g): | |
125 """ | |
126 add this graph to the total, call onChange, and then revert | |
127 the addition of this graph | |
128 """ | |
129 self._oneShotAdditionGraph = g | |
130 self._combinedGraph = None | |
131 try: | |
132 self.onChange(self, oneShot=True, oneShotGraph=g) | |
133 finally: | |
134 self._oneShotAdditionGraph = None | |
135 self._combinedGraph = None | |
136 | |
1086 | 137 def addOneShotFromString(self, body, contentType): |
138 g = parseRdf(body, contentType) | |
139 if not len(g): | |
140 log.warn("incoming oneshot graph had no statements: %r", body) | |
141 return 0 | |
142 t1 = time.time() | |
143 self.addOneShot(g) | |
144 return time.time() - t1 | |
145 | |
1080 | 146 def getGraph(self): |
147 """rdflib Graph with the file+remote contents of the input graph""" | |
148 # this could be much faster with the combined readonly graph | |
149 # view from rdflib | |
150 if self._combinedGraph is None: | |
151 self._combinedGraph = Graph() | |
152 if self._fileGraph: | |
153 for s in self._fileGraph: | |
154 self._combinedGraph.add(s) | |
1108
8caf62030955
reasoning uses sse_collector
drewp <drewp@bigasterisk.com>
parents:
1086
diff
changeset
|
155 for s in self._remoteData.graph: |
8caf62030955
reasoning uses sse_collector
drewp <drewp@bigasterisk.com>
parents:
1086
diff
changeset
|
156 self._combinedGraph.add(s) |
1080 | 157 if self._oneShotAdditionGraph: |
158 for s in self._oneShotAdditionGraph: | |
159 self._combinedGraph.add(s) | |
160 | |
161 return self._combinedGraph |