forked from jmandel/testing-ghpages
/
index.html
234 lines (177 loc) · 11.5 KB
/
index.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>HOWTO Build SMART Background and Helper Apps</title>
<meta name="author" content="SMART Platforms">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<!-- Le HTML5 shim, for IE6-8 support of HTML elements -->
<!--[if lt IE 9]>
<script src="http://html5shim.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
<link href="/assets/themes/twitter-2.0/css/pygments.css" rel="stylesheet">
<link href="/assets/themes/twitter-2.0/css/bootstrap.min.css" rel="stylesheet">
<link href="/assets/themes/twitter-2.0/css/bootstrap-responsive.min.css" rel="stylesheet">
<link href="/assets/themes/twitter-2.0/css/style.css" rel="stylesheet">
</head>
<body>
<div class="container">
<div class="content">
<section id="jekyll-page">
<div class="row">
<div class="span4">
<a href="/">
<img id='smart_top_logo' src="/images/smart.png"/>
</a>
<div id="left_nav">
<ul class="nav nav-list">
<li class="nav-header">Tutorials</li>
<li><a href="/howto/build_a_smart_app">Build a SMART App</a></li>
<li><a href="/howto/build_a_rest_app">Build a SMART REST App</a></li>
<li><a href="/howto/background_and_helper_apps">Background + Helper Apps</a></li>
<li><a href="/howto/build_smart_frame_ui_apps">Frame UI Apps</a></li>
<li><a href="/howto/got_statins">Got Statins? App</a></li>
<li><a href="/howto/rx_reminder">RxReminder App</a></li>
<li class="nav-header">Using SMART Data</li>
<li><a href="/howto/intro_to_rdf">Intro to RDF and SPARQL</a></li>
<li><a href="/howto/sparql_examples">SPARQL Examples for SMART</a></li>
<li><a href="/howto/intro_to_jsonld">Intro to the JSON-LD API</a></li>
<li><a href="/howto/filters">Query Filtering and Pagination</a></li>
<li><a href="/howto/deferred">$.Deferred for Parallel Queries</a></li>
<li><a href="/howto/smart_data">SMART Data: Best Practices</a></li>
<li class="nav-header">Reference</li>
<li><a href="/reference/data_model">Data Model</a></li>
<li><a href="/reference/rest_api">REST API</a></li>
<li><a href="/reference/filters">Query Filters</a></li>
<li><a href="/reference/app_manifest">App Manifest</a></li>
<li class="nav-header">Client Libraries</li>
<li><a href="/libraries/javascript">Javascript (SMART Connect)</a></li>
<li><a href="/libraries/python">Python</a></li>
<li><a href="/libraries/java">Java</a></li>
<li><a href="/libraries/dotnet">.NET</a></li>
<li><a href="/libraries/container_javascript">Container-side Javascript</a></li>
<li class="nav-header">SMART Update Guides</li>
<li><a href="/updates/smart_0.4/app">0.4 Apps</a></li>
<li><a href="/updates/smart_0.4/container">0.4 Containers</a></li>
<li><a href="/updates/smart_0.5/">0.5 Apps + Containers</a></li>
<li class="nav-header">Reference EMR Installation</li>
<li><a href="/install/linux">Ubuntu Linux</a></li>
<li><a href="/install/os_x">OS X</a></li>
<li class="nav-header">Presentations</li>
<li><a href="http://www.slideshare.net/jmandel/2010-0826smartarchitecture">Architecture (2010-08)</a></li>
<li><a href="http://www.slideshare.net/jmandel/2010-08-26-smart-governance">Governance (2010-08)</a></li>
<li><a href="http://media.smartplatforms.org/smart-screencast.mp4">Demo</a></li>
<li class="nav-header">Downloads</li>
<li><a href="/downloads/">Download Source + VM</a></li>
</ul>
</div>
</div>
<div class="span8" id="jekyll-page-content">
<div class="page-header">
<h1>HOWTO Build SMART Background and Helper Apps <small></small></h1>
</div>
<h2>Background Apps</h2>
<p><a href="/images/background_app.png" target="_blank">
<img src="/images/background_app.png"
style="width: 100%; display: block; margin: 20px auto;">
</a></p>
<div class='simple_small_box'>Help us improve! You can correct errors or add to this page by clicking
<a class='githublink' href=''>here</a> to edit this page on Github.
</div>
<p>So far, we have talked about SMART apps that access medical record data on
behalf of an active user of the EMR/PCHR/data-mining platform. What about apps
that autonomously take action when no one is logged in? An app might want to
check every medical record for a particular datapoint (e.g. a recalled drug).
The SMART Platform supports this background app use case as follows:</p>
<ul>
<li>the app is specially authorized to loop through every known record in the system</li>
<li>on each looped record, the app obtains OAuth credentials necessary to access that one record.</li>
<li>for each record, the app can access the SMART REST API as it normally would, using the credentials obtained for that record. </li>
</ul>
<p>Importantly, a background app is not necessarily a web app, since it may not
have a user-facing web interface. In this example, we will demonstrate just
that: a simple Python program that acts as a SMART background app, but does not
respond to any web requests. So, if you've figured out how to build a SMART REST
app, all you need to know now is how to obtain the credentials needed to cycle
through all the SMART Container's medical records.</p>
<p>The first thing you need is, of course, a SmartClient instance to make REST API
calls against the SMART container. If you don't have that library running yet,
check out the SMART Python Client. </p>
<p>Make sure you understand the warning about setting a strong <code>consumer_secret</code>
in production <a href="/howto/build_a_rest_app/#consumer_secret_warning">here</a></p>
<p>Then:</p>
<div class="highlight"><pre><code class="python"> <span class="n">smart_client</span> <span class="o">=</span> <span class="n">smart</span><span class="o">.</span><span class="n">SmartClient</span><span class="p">(</span>
<span class="s">'smart-background-app@apps.smartplatforms.org'</span><span class="p">,</span>
<span class="p">{</span><span class="s">'api_base'</span> <span class="p">:</span> <span class="s">'http://sandbox-api.smartplatforms.org'</span><span class="p">},</span>
<span class="p">{</span>
<span class="s">'consumer_key'</span> <span class="p">:</span> <span class="s">'smart-background-app@apps.smartplatforms.org'</span><span class="p">,</span>
<span class="s">'consumer_secret'</span> <span class="p">:</span> <span class="s">'smartapp-secret'</span>
<span class="p">},</span>
<span class="bp">None</span><span class="p">)</span>
</code></pre></div>
<p>The important difference between this SmartClient and the one you created for
use in SMART REST API calls is that this one has no resource-specific
credentials. That's because, at first, you're not going to make API calls
specific to any single medical record. In OAuth parlance, this is called a
"2-legged call." Now, it's time to iterate through all records available at that
SMART Container. The specific API calls to do this can be found in our REST API,
but the SMART Python client library makes it easy for you:</p>
<div class="highlight"><pre><code class="python"> <span class="k">for</span> <span class="n">record_id</span> <span class="ow">in</span> <span class="n">smart_client</span><span class="o">.</span><span class="n">loop_over_records</span><span class="p">():</span>
<span class="c"># do stuff with each record</span>
</code></pre></div>
<p>Note that, in each iteration, the smart<em>client is modified to automatically use
the credentials needed to access this specific record. If you were to call the
API manually, you would have to extract the tokens you get from the container,
and insert them into the smart</em>client object.</p>
<p>So, using a simple query to read drug names:</p>
<div class="highlight"><pre><code class="python"> <span class="n">QUERY</span> <span class="o">=</span> <span class="s">"""</span>
<span class="s"> PREFIX dcterms:<http://purl.org/dc/terms/></span>
<span class="s"> PREFIX sp:<http://smartplatforms.org/terms#></span>
<span class="s"> PREFIX rdf:<http://www.w3.org/1999/02/22-rdf-syntax-ns#></span>
<span class="s"> SELECT ?drugname</span>
<span class="s"> WHERE {</span>
<span class="s"> ?med rdf:type sp:Medication .</span>
<span class="s"> ?med sp:drugName ?drugname_code .</span>
<span class="s"> ?drugname_code dcterms:title ?drugname .</span>
<span class="s"> }</span>
<span class="s"> """</span>
</code></pre></div>
<p>We can simply iterate through the records, retrieve each record's medications,
and print them to the screen:</p>
<div class="highlight"><pre><code class="python"> <span class="k">for</span> <span class="n">record_id</span> <span class="ow">in</span> <span class="n">smart_client</span><span class="o">.</span><span class="n">loop_over_records</span><span class="p">():</span>
<span class="n">medications</span> <span class="o">=</span> <span class="n">smart_client</span><span class="o">.</span><span class="n">get_medications</span><span class="p">(</span><span class="n">record_id</span> <span class="o">=</span> <span class="n">record_id</span><span class="p">)</span>
<span class="n">med_names</span> <span class="o">=</span> <span class="n">medications</span><span class="o">.</span><span class="n">graph</span><span class="o">.</span><span class="n">query</span><span class="p">(</span><span class="n">QUERY</span><span class="p">)</span>
<span class="k">print</span> <span class="s">"</span><span class="si">%s</span><span class="s">: </span><span class="si">%s</span><span class="s">"</span> <span class="o">%</span> <span class="p">(</span><span class="n">record_id</span><span class="p">,</span> <span class="s">", "</span><span class="o">.</span><span class="n">join</span><span class="p">([</span><span class="nb">str</span><span class="p">(</span><span class="n">m</span><span class="p">)</span> <span class="k">for</span> <span class="n">m</span> <span class="ow">in</span> <span class="n">med_names</span><span class="p">]))</span>
</code></pre></div>
<h2>Helper Apps</h2>
<p>You now know how to build simple SMART apps in HTML and JavaScript, SMART apps
that make REST API calls, and SMART apps that run entirely in the background
without a UI. What about apps that provide services to other apps? These we call
Helper Apps.</p>
</div>
</div>
</section>
</div>
<footer>
<div>
<a href='http://smartplatforms.org'>SMART Platforms</a> © 2012
</div>
</footer>
</div>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
<script>window.jQuery || document.write('<script src="/assets/themes/twitter-2.0/js/jquery.min.js"><\/script>')</script>
<script src="/assets/themes/twitter-2.0/js/bootstrap_aks.js"></script>
<script type="text/javascript">
var _gaq = _gaq || [];
_gaq.push(['_setAccount', 'UA-33617191-1']);
_gaq.push(['_trackPageview']);
(function() {
var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
})();
</script>
<script src="/assets/app.js?v=0.1"></script>
<script>Toc.init($("#jekyll-page-content"), $("#toc"));</script>
</body>
</html>