├── .gitignore ├── 1_Expand_and_Capture.ipynb ├── 2_Data_Exchange.ipynb ├── 3_SoS_Magics.html ├── 3_SoS_Magics.ipynb ├── 4_Notebook_to_Workflow.ipynb ├── 5_Workflow_features.ipynb ├── 6_Task.ipynb ├── Dockerfile ├── LICENSE ├── README.md ├── REQUIRE ├── python-and-julia.ipynb ├── python-and-r.ipynb └── sos-notebook.png /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | wheels/ 23 | *.egg-info/ 24 | .installed.cfg 25 | *.egg 26 | MANIFEST 27 | 28 | # PyInstaller 29 | # Usually these files are written by a python script from a template 30 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 31 | *.manifest 32 | *.spec 33 | 34 | # Installer logs 35 | pip-log.txt 36 | pip-delete-this-directory.txt 37 | 38 | # Unit test / coverage reports 39 | htmlcov/ 40 | .tox/ 41 | .coverage 42 | .coverage.* 43 | .cache 44 | nosetests.xml 45 | coverage.xml 46 | *.cover 47 | .hypothesis/ 48 | .pytest_cache/ 49 | 50 | # Translations 51 | *.mo 52 | *.pot 53 | 54 | # Django stuff: 55 | *.log 56 | local_settings.py 57 | db.sqlite3 58 | 59 | # Flask stuff: 60 | instance/ 61 | .webassets-cache 62 | 63 | # Scrapy stuff: 64 | .scrapy 65 | 66 | # Sphinx documentation 67 | docs/_build/ 68 | 69 | # PyBuilder 70 | target/ 71 | 72 | # Jupyter Notebook 73 | .ipynb_checkpoints 74 | 75 | # pyenv 76 | .python-version 77 | 78 | # celery beat schedule file 79 | celerybeat-schedule 80 | 81 | # SageMath parsed files 82 | *.sage.py 83 | 84 | # Environments 85 | .env 86 | .venv 87 | env/ 88 | venv/ 89 | ENV/ 90 | env.bak/ 91 | venv.bak/ 92 | 93 | # Spyder project settings 94 | .spyderproject 95 | .spyproject 96 | 97 | # Rope project settings 98 | .ropeproject 99 | 100 | # mkdocs documentation 101 | /site 102 | 103 | # mypy 104 | .mypy_cache/ 105 | -------------------------------------------------------------------------------- /1_Expand_and_Capture.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": { 6 | "kernel": "SoS" 7 | }, 8 | "source": [ 9 | "# Working with subkernels" 10 | ] 11 | }, 12 | { 13 | "cell_type": "markdown", 14 | "metadata": { 15 | "kernel": "SoS" 16 | }, 17 | "source": [ 18 | "Unless you would like to start multiple versions of the same kernel or link a language module to a kernel that is not recognized by SoS, you can start a subkernel simply by selecting the language from the language dropdown to the top right corner of each cell." 19 | ] 20 | }, 21 | { 22 | "cell_type": "markdown", 23 | "metadata": { 24 | "kernel": "SoS" 25 | }, 26 | "source": [ 27 | "## Sending input to subkernel" 28 | ] 29 | }, 30 | { 31 | "cell_type": "markdown", 32 | "metadata": { 33 | "kernel": "SoS" 34 | }, 35 | "source": [ 36 | "The SoS language is based on Python 3.6+ so \n", 37 | "any python statements are acceptable\n" 38 | ] 39 | }, 40 | { 41 | "cell_type": "code", 42 | "execution_count": 1, 43 | "metadata": { 44 | "kernel": "SoS" 45 | }, 46 | "outputs": [], 47 | "source": [ 48 | "filename = '1_Expand_and_Capture.ipynb'" 49 | ] 50 | }, 51 | { 52 | "cell_type": "code", 53 | "execution_count": 2, 54 | "metadata": { 55 | "kernel": "Bash", 56 | "scrolled": true 57 | }, 58 | "outputs": [ 59 | { 60 | "name": "stdout", 61 | "output_type": "stream", 62 | "text": [ 63 | " 352 1_Expand_and_Capture.ipynb\n" 64 | ] 65 | } 66 | ], 67 | "source": [ 68 | "wc -l 1_Expand_and_Capture.ipynb" 69 | ] 70 | }, 71 | { 72 | "cell_type": "markdown", 73 | "metadata": { 74 | "kernel": "Bash" 75 | }, 76 | "source": [ 77 | "With magic `%expand`, cell content is expanded as Python f-string before sending to the subkernel" 78 | ] 79 | }, 80 | { 81 | "cell_type": "code", 82 | "execution_count": 3, 83 | "metadata": { 84 | "kernel": "Bash" 85 | }, 86 | "outputs": [ 87 | { 88 | "name": "stdout", 89 | "output_type": "stream", 90 | "text": [ 91 | " 352 1_Expand_and_Capture.ipynb\n" 92 | ] 93 | } 94 | ], 95 | "source": [ 96 | "%expand\n", 97 | "wc -l {filename}" 98 | ] 99 | }, 100 | { 101 | "cell_type": "code", 102 | "execution_count": 4, 103 | "metadata": { 104 | "kernel": "JavaScript" 105 | }, 106 | "outputs": [ 107 | { 108 | "data": { 109 | "text/plain": [ 110 | "{ cells: \n", 111 | " [ { cell_type: 'markdown', metadata: [Object], source: [Array] },\n", 112 | " { cell_type: 'markdown', metadata: [Object], source: [Array] },\n", 113 | " { cell_type: 'markdown', metadata: [Object], source: [Array] },\n", 114 | " { cell_type: 'markdown', metadata: [Object], source: [Array] },\n", 115 | " { cell_type: 'code',\n", 116 | " execution_count: 1,\n", 117 | " metadata: [Object],\n", 118 | " outputs: [],\n", 119 | " source: [Array] },\n", 120 | " { cell_type: 'code',\n", 121 | " execution_count: 2,\n", 122 | " metadata: [Object],\n", 123 | " outputs: [Array],\n", 124 | " source: [Array] },\n", 125 | " { cell_type: 'markdown', metadata: [Object], source: [Array] },\n", 126 | " { cell_type: 'code',\n", 127 | " execution_count: 3,\n", 128 | " metadata: [Object],\n", 129 | " outputs: [Array],\n", 130 | " source: [Array] },\n", 131 | " { cell_type: 'code',\n", 132 | " execution_count: 4,\n", 133 | " metadata: [Object],\n", 134 | " outputs: [Array],\n", 135 | " source: [Array] },\n", 136 | " { cell_type: 'markdown', metadata: [Object], source: [Array] },\n", 137 | " { cell_type: 'code',\n", 138 | " execution_count: 5,\n", 139 | " metadata: [Object],\n", 140 | " outputs: [Array],\n", 141 | " source: [Array] },\n", 142 | " { cell_type: 'code',\n", 143 | " execution_count: 6,\n", 144 | " metadata: [Object],\n", 145 | " outputs: [Array],\n", 146 | " source: [Array] },\n", 147 | " { cell_type: 'code',\n", 148 | " execution_count: 7,\n", 149 | " metadata: [Object],\n", 150 | " outputs: [Array],\n", 151 | " source: [Array] },\n", 152 | " { cell_type: 'code',\n", 153 | " execution_count: 8,\n", 154 | " metadata: [Object],\n", 155 | " outputs: [Array],\n", 156 | " source: [Array] } ],\n", 157 | " metadata: \n", 158 | " { kernelspec: { display_name: 'SoS', language: 'sos', name: 'sos' },\n", 159 | " language_info: \n", 160 | " { codemirror_mode: 'sos',\n", 161 | " file_extension: '.sos',\n", 162 | " mimetype: 'text/x-sos',\n", 163 | " name: 'sos',\n", 164 | " nbconvert_exporter: 'sos_notebook.converter.SoS_Exporter',\n", 165 | " pygments_lexer: 'sos' },\n", 166 | " sos: { kernels: [Array], panel: [Object], version: '0.9.16.7' } },\n", 167 | " nbformat: 4,\n", 168 | " nbformat_minor: 2 }" 169 | ] 170 | }, 171 | "execution_count": 4, 172 | "metadata": {}, 173 | "output_type": "execute_result" 174 | } 175 | ], 176 | "source": [ 177 | "%expand\n", 178 | "var fs = require('fs');\n", 179 | "JSON.parse(fs.readFileSync(\"{filename}\", 'utf8'));" 180 | ] 181 | }, 182 | { 183 | "cell_type": "markdown", 184 | "metadata": { 185 | "kernel": "JavaScript" 186 | }, 187 | "source": [ 188 | "## Capture output from subkernels" 189 | ] 190 | }, 191 | { 192 | "cell_type": "code", 193 | "execution_count": 5, 194 | "metadata": { 195 | "kernel": "Bash" 196 | }, 197 | "outputs": [ 198 | { 199 | "name": "stdout", 200 | "output_type": "stream", 201 | "text": [ 202 | " 352 1_Expand_and_Capture.ipynb\n" 203 | ] 204 | } 205 | ], 206 | "source": [ 207 | "%capture --to res\n", 208 | "%expand\n", 209 | "wc -l {filename}" 210 | ] 211 | }, 212 | { 213 | "cell_type": "code", 214 | "execution_count": 6, 215 | "metadata": { 216 | "kernel": "SoS" 217 | }, 218 | "outputs": [ 219 | { 220 | "data": { 221 | "text/plain": [ 222 | "' 352 1_Expand_and_Capture.ipynb\\n'" 223 | ] 224 | }, 225 | "execution_count": 6, 226 | "metadata": {}, 227 | "output_type": "execute_result" 228 | } 229 | ], 230 | "source": [ 231 | "res" 232 | ] 233 | }, 234 | { 235 | "cell_type": "code", 236 | "execution_count": 7, 237 | "metadata": { 238 | "kernel": "sparql" 239 | }, 240 | "outputs": [ 241 | { 242 | "data": { 243 | "text/html": [ 244 | "
Endpoint set to: http://dbpedia.org/sparql
Display: table
" 245 | ], 246 | "text/plain": [ 247 | "Endpoint set to: http://dbpedia.org/sparql\n", 248 | "Display: table\n" 249 | ] 250 | }, 251 | "metadata": {}, 252 | "output_type": "display_data" 253 | }, 254 | { 255 | "data": { 256 | "text/html": [ 257 | "
property
http://www.w3.org/2002/07/owl#differentFrom
http://www.w3.org/2000/01/rdf-schema#seeAlso
http://www.w3.org/2002/07/owl#sameAs
Total: 3, Shown: 3
" 258 | ] 259 | }, 260 | "metadata": {}, 261 | "output_type": "display_data" 262 | } 263 | ], 264 | "source": [ 265 | "%capture html --to result\n", 266 | "\n", 267 | "%endpoint http://dbpedia.org/sparql\n", 268 | "%display table \n", 269 | "SELECT DISTINCT ?property\n", 270 | "WHERE {\n", 271 | " ?s ?property ?person .\n", 272 | " ?person rdf:type foaf:Person .\n", 273 | "}\n", 274 | "LIMIT 3" 275 | ] 276 | }, 277 | { 278 | "cell_type": "code", 279 | "execution_count": 8, 280 | "metadata": { 281 | "kernel": "SoS" 282 | }, 283 | "outputs": [ 284 | { 285 | "data": { 286 | "text/plain": [ 287 | "['http://www.w3.org/2002/07/owl#differentFrom',\n", 288 | " 'http://www.w3.org/2000/01/rdf-schema#seeAlso',\n", 289 | " 'http://www.w3.org/2002/07/owl#sameAs']" 290 | ] 291 | }, 292 | "execution_count": 8, 293 | "metadata": {}, 294 | "output_type": "execute_result" 295 | } 296 | ], 297 | "source": [ 298 | "from bs4 import BeautifulSoup as Soup\n", 299 | "html = Soup(result, 'html.parser') \n", 300 | "[a['href'] for a in html.find_all('a')]" 301 | ] 302 | } 303 | ], 304 | "metadata": { 305 | "kernelspec": { 306 | "display_name": "SoS", 307 | "language": "sos", 308 | "name": "sos" 309 | }, 310 | "language_info": { 311 | "codemirror_mode": "sos", 312 | "file_extension": ".sos", 313 | "mimetype": "text/x-sos", 314 | "name": "sos", 315 | "nbconvert_exporter": "sos_notebook.converter.SoS_Exporter", 316 | "pygments_lexer": "sos" 317 | }, 318 | "sos": { 319 | "kernels": [ 320 | [ 321 | "Bash", 322 | "bash", 323 | "Bash", 324 | "#E6EEFF" 325 | ], 326 | [ 327 | "JavaScript", 328 | "javascript", 329 | "JavaScript", 330 | "#c8e1ae" 331 | ], 332 | [ 333 | "SoS", 334 | "sos", 335 | "", 336 | "" 337 | ] 338 | ], 339 | "panel": { 340 | "displayed": true, 341 | "height": "251.571px", 342 | "style": "side" 343 | }, 344 | "version": "0.9.16.7" 345 | } 346 | }, 347 | "nbformat": 4, 348 | "nbformat_minor": 2 349 | } 350 | -------------------------------------------------------------------------------- /2_Data_Exchange.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": { 6 | "kernel": "SoS" 7 | }, 8 | "source": [ 9 | "# Exchange of variables" 10 | ] 11 | }, 12 | { 13 | "cell_type": "markdown", 14 | "metadata": { 15 | "kernel": "SoS" 16 | }, 17 | "source": [ 18 | "## Three ways of transferring variables" 19 | ] 20 | }, 21 | { 22 | "cell_type": "markdown", 23 | "metadata": { 24 | "kernel": "SoS" 25 | }, 26 | "source": [ 27 | "### Magic `%get` and `%put`" 28 | ] 29 | }, 30 | { 31 | "cell_type": "code", 32 | "execution_count": 1, 33 | "metadata": { 34 | "kernel": "SoS" 35 | }, 36 | "outputs": [], 37 | "source": [ 38 | "n=5" 39 | ] 40 | }, 41 | { 42 | "cell_type": "code", 43 | "execution_count": 2, 44 | "metadata": { 45 | "kernel": "R" 46 | }, 47 | "outputs": [], 48 | "source": [ 49 | "%get n\n", 50 | "rn <- rnorm(n)" 51 | ] 52 | }, 53 | { 54 | "cell_type": "code", 55 | "execution_count": 3, 56 | "metadata": { 57 | "kernel": "SoS" 58 | }, 59 | "outputs": [ 60 | { 61 | "data": { 62 | "text/plain": [ 63 | "[-0.717208726490722,\n", 64 | " -0.716307792602076,\n", 65 | " 0.210121660734453,\n", 66 | " -1.50107629089392,\n", 67 | " 0.105600079729086]" 68 | ] 69 | }, 70 | "execution_count": 3, 71 | "metadata": {}, 72 | "output_type": "execute_result" 73 | } 74 | ], 75 | "source": [ 76 | "%get rn --from R\n", 77 | "rn" 78 | ] 79 | }, 80 | { 81 | "cell_type": "code", 82 | "execution_count": 4, 83 | "metadata": { 84 | "kernel": "SoS" 85 | }, 86 | "outputs": [], 87 | "source": [ 88 | "rn = [x+1 for x in rn]" 89 | ] 90 | }, 91 | { 92 | "cell_type": "code", 93 | "execution_count": 5, 94 | "metadata": { 95 | "kernel": "SoS" 96 | }, 97 | "outputs": [], 98 | "source": [ 99 | "%put rn --to R" 100 | ] 101 | }, 102 | { 103 | "cell_type": "code", 104 | "execution_count": 6, 105 | "metadata": { 106 | "kernel": "R" 107 | }, 108 | "outputs": [ 109 | { 110 | "data": { 111 | "text/html": [ 112 | "
    \n", 113 | "\t
  1. 0.282791273509278
  2. \n", 114 | "\t
  3. 0.283692207397924
  4. \n", 115 | "\t
  5. 1.21012166073445
  6. \n", 116 | "\t
  7. -0.50107629089392
  8. \n", 117 | "\t
  9. 1.10560007972909
  10. \n", 118 | "
\n" 119 | ], 120 | "text/latex": [ 121 | "\\begin{enumerate*}\n", 122 | "\\item 0.282791273509278\n", 123 | "\\item 0.283692207397924\n", 124 | "\\item 1.21012166073445\n", 125 | "\\item -0.50107629089392\n", 126 | "\\item 1.10560007972909\n", 127 | "\\end{enumerate*}\n" 128 | ], 129 | "text/markdown": [ 130 | "1. 0.282791273509278\n", 131 | "2. 0.283692207397924\n", 132 | "3. 1.21012166073445\n", 133 | "4. -0.50107629089392\n", 134 | "5. 1.10560007972909\n", 135 | "\n", 136 | "\n" 137 | ], 138 | "text/plain": [ 139 | "[1] 0.2827913 0.2836922 1.2101217 -0.5010763 1.1056001" 140 | ] 141 | }, 142 | "metadata": {}, 143 | "output_type": "display_data" 144 | } 145 | ], 146 | "source": [ 147 | "rn" 148 | ] 149 | }, 150 | { 151 | "cell_type": "markdown", 152 | "metadata": { 153 | "kernel": "R" 154 | }, 155 | "source": [ 156 | "### Magic `%with`" 157 | ] 158 | }, 159 | { 160 | "cell_type": "code", 161 | "execution_count": 7, 162 | "metadata": { 163 | "kernel": "SoS" 164 | }, 165 | "outputs": [], 166 | "source": [ 167 | "n=5" 168 | ] 169 | }, 170 | { 171 | "cell_type": "code", 172 | "execution_count": 8, 173 | "metadata": { 174 | "kernel": "R" 175 | }, 176 | "outputs": [], 177 | "source": [ 178 | "%with R -i n -o rn\n", 179 | "rn <- rnorm(n)" 180 | ] 181 | }, 182 | { 183 | "cell_type": "code", 184 | "execution_count": 9, 185 | "metadata": { 186 | "kernel": "SoS" 187 | }, 188 | "outputs": [ 189 | { 190 | "data": { 191 | "text/plain": [ 192 | "[-0.200078426229837,\n", 193 | " -0.425017555400589,\n", 194 | " 0.749107473681659,\n", 195 | " -0.333266605572932,\n", 196 | " 1.09653643921428]" 197 | ] 198 | }, 199 | "execution_count": 9, 200 | "metadata": {}, 201 | "output_type": "execute_result" 202 | } 203 | ], 204 | "source": [ 205 | "rn" 206 | ] 207 | }, 208 | { 209 | "cell_type": "markdown", 210 | "metadata": { 211 | "kernel": "SoS" 212 | }, 213 | "source": [ 214 | "### `sos`-named Variables" 215 | ] 216 | }, 217 | { 218 | "cell_type": "code", 219 | "execution_count": 10, 220 | "metadata": { 221 | "kernel": "SoS" 222 | }, 223 | "outputs": [], 224 | "source": [ 225 | "sos_n = 5" 226 | ] 227 | }, 228 | { 229 | "cell_type": "code", 230 | "execution_count": 11, 231 | "metadata": { 232 | "kernel": "R" 233 | }, 234 | "outputs": [], 235 | "source": [ 236 | "sos_rn <- rnorm(sos_n)" 237 | ] 238 | }, 239 | { 240 | "cell_type": "code", 241 | "execution_count": 12, 242 | "metadata": { 243 | "kernel": "SoS" 244 | }, 245 | "outputs": [ 246 | { 247 | "data": { 248 | "text/plain": [ 249 | "[-0.493718017873675,\n", 250 | " 0.00641199595342825,\n", 251 | " 3.18527800389836,\n", 252 | " -0.53589119458946,\n", 253 | " 1.3786041453922]" 254 | ] 255 | }, 256 | "execution_count": 12, 257 | "metadata": {}, 258 | "output_type": "execute_result" 259 | } 260 | ], 261 | "source": [ 262 | "sos_rn" 263 | ] 264 | }, 265 | { 266 | "cell_type": "markdown", 267 | "metadata": { 268 | "kernel": "SoS" 269 | }, 270 | "source": [ 271 | "## Transfer variables of other types" 272 | ] 273 | }, 274 | { 275 | "cell_type": "code", 276 | "execution_count": 13, 277 | "metadata": { 278 | "kernel": "R" 279 | }, 280 | "outputs": [], 281 | "source": [ 282 | "a = 3\n", 283 | "b = c(3, 2, 1)" 284 | ] 285 | }, 286 | { 287 | "cell_type": "code", 288 | "execution_count": 14, 289 | "metadata": { 290 | "kernel": "SoS" 291 | }, 292 | "outputs": [], 293 | "source": [ 294 | "%get a b --from R" 295 | ] 296 | }, 297 | { 298 | "cell_type": "code", 299 | "execution_count": 15, 300 | "metadata": { 301 | "kernel": "SoS" 302 | }, 303 | "outputs": [ 304 | { 305 | "data": { 306 | "text/plain": [ 307 | "3" 308 | ] 309 | }, 310 | "execution_count": 15, 311 | "metadata": {}, 312 | "output_type": "execute_result" 313 | } 314 | ], 315 | "source": [ 316 | "a" 317 | ] 318 | }, 319 | { 320 | "cell_type": "code", 321 | "execution_count": 16, 322 | "metadata": { 323 | "kernel": "SoS" 324 | }, 325 | "outputs": [ 326 | { 327 | "data": { 328 | "text/plain": [ 329 | "[3, 2, 1]" 330 | ] 331 | }, 332 | "execution_count": 16, 333 | "metadata": {}, 334 | "output_type": "execute_result" 335 | } 336 | ], 337 | "source": [ 338 | "b" 339 | ] 340 | }, 341 | { 342 | "cell_type": "code", 343 | "execution_count": 17, 344 | "metadata": { 345 | "kernel": "SoS" 346 | }, 347 | "outputs": [ 348 | { 349 | "name": "stderr", 350 | "output_type": "stream", 351 | "text": [ 352 | "Loading required package: feather\n" 353 | ] 354 | }, 355 | { 356 | "data": { 357 | "text/html": [ 358 | "
\n", 359 | "\n", 372 | "\n", 373 | " \n", 374 | " \n", 375 | " \n", 376 | " \n", 377 | " \n", 378 | " \n", 379 | " \n", 380 | " \n", 381 | " \n", 382 | " \n", 383 | " \n", 384 | " \n", 385 | " \n", 386 | " \n", 387 | " \n", 388 | " \n", 389 | " \n", 390 | " \n", 391 | " \n", 392 | " \n", 393 | " \n", 394 | " \n", 395 | " \n", 396 | " \n", 397 | " \n", 398 | " \n", 399 | " \n", 400 | " \n", 401 | " \n", 402 | " \n", 403 | " \n", 404 | " \n", 405 | " \n", 406 | " \n", 407 | " \n", 408 | " \n", 409 | " \n", 410 | " \n", 411 | " \n", 412 | " \n", 413 | " \n", 414 | " \n", 415 | " \n", 416 | " \n", 417 | " \n", 418 | " \n", 419 | " \n", 420 | " \n", 421 | " \n", 422 | " \n", 423 | " \n", 424 | " \n", 425 | " \n", 426 | " \n", 427 | " \n", 428 | " \n", 429 | " \n", 430 | " \n", 431 | " \n", 432 | " \n", 433 | " \n", 434 | " \n", 435 | " \n", 436 | " \n", 437 | " \n", 438 | " \n", 439 | " \n", 440 | " \n", 441 | " \n", 442 | " \n", 443 | " \n", 444 | " \n", 445 | " \n", 446 | " \n", 447 | " \n", 448 | " \n", 449 | " \n", 450 | " \n", 451 | " \n", 452 | " \n", 453 | " \n", 454 | " \n", 455 | " \n", 456 | " \n", 457 | " \n", 458 | " \n", 459 | " \n", 460 | " \n", 461 | " \n", 462 | " \n", 463 | " \n", 464 | " \n", 465 | " \n", 466 | " \n", 467 | " \n", 468 | " \n", 469 | " \n", 470 | " \n", 471 | " \n", 472 | " \n", 473 | " \n", 474 | " \n", 475 | " \n", 476 | " \n", 477 | " \n", 478 | " \n", 479 | " \n", 480 | " \n", 481 | " \n", 482 | " \n", 483 | " \n", 484 | " \n", 485 | " \n", 486 | " \n", 487 | " \n", 488 | " \n", 489 | " \n", 490 | " \n", 491 | " \n", 492 | " \n", 493 | " \n", 494 | " \n", 495 | " \n", 496 | " \n", 497 | " \n", 498 | " \n", 499 | " \n", 500 | " \n", 501 | " \n", 502 | " \n", 503 | " \n", 504 | " \n", 505 | " \n", 506 | " \n", 507 | " \n", 508 | " \n", 509 | " \n", 510 | " \n", 511 | " \n", 512 | " \n", 513 | " \n", 514 | " \n", 515 | " \n", 516 | " \n", 517 | " \n", 518 | " \n", 519 | " \n", 520 | " \n", 521 | " \n", 522 | " \n", 523 | " \n", 524 | " \n", 525 | " \n", 526 | " \n", 527 | " \n", 528 | " \n", 529 | " \n", 530 | " \n", 531 | " \n", 532 | " \n", 533 | " \n", 534 | " \n", 535 | " \n", 536 | " \n", 537 | " \n", 538 | " \n", 539 | " \n", 540 | " \n", 541 | " \n", 542 | " \n", 543 | " \n", 544 | " \n", 545 | " \n", 546 | " \n", 547 | " \n", 548 | " \n", 549 | " \n", 550 | " \n", 551 | " \n", 552 | " \n", 553 | " \n", 554 | " \n", 555 | " \n", 556 | " \n", 557 | " \n", 558 | " \n", 559 | " \n", 560 | " \n", 561 | " \n", 562 | " \n", 563 | " \n", 564 | " \n", 565 | " \n", 566 | " \n", 567 | " \n", 568 | " \n", 569 | " \n", 570 | " \n", 571 | " \n", 572 | " \n", 573 | " \n", 574 | " \n", 575 | " \n", 576 | " \n", 577 | " \n", 578 | " \n", 579 | " \n", 580 | " \n", 581 | " \n", 582 | " \n", 583 | " \n", 584 | " \n", 585 | " \n", 586 | " \n", 587 | " \n", 588 | " \n", 589 | " \n", 590 | " \n", 591 | " \n", 592 | " \n", 593 | " \n", 594 | " \n", 595 | " \n", 596 | " \n", 597 | " \n", 598 | " \n", 599 | " \n", 600 | " \n", 601 | " \n", 602 | " \n", 603 | " \n", 604 | " \n", 605 | " \n", 606 | " \n", 607 | " \n", 608 | " \n", 609 | " \n", 610 | " \n", 611 | " \n", 612 | " \n", 613 | " \n", 614 | " \n", 615 | " \n", 616 | " \n", 617 | " \n", 618 | " \n", 619 | " \n", 620 | " \n", 621 | " \n", 622 | " \n", 623 | " \n", 624 | " \n", 625 | " \n", 626 | " \n", 627 | " \n", 628 | " \n", 629 | " \n", 630 | " \n", 631 | " \n", 632 | " \n", 633 | " \n", 634 | " \n", 635 | " \n", 636 | " \n", 637 | " \n", 638 | " \n", 639 | " \n", 640 | " \n", 641 | " \n", 642 | " \n", 643 | " \n", 644 | " \n", 645 | " \n", 646 | " \n", 647 | " \n", 648 | " \n", 649 | " \n", 650 | " \n", 651 | " \n", 652 | " \n", 653 | " \n", 654 | " \n", 655 | " \n", 656 | " \n", 657 | " \n", 658 | " \n", 659 | " \n", 660 | " \n", 661 | " \n", 662 | " \n", 663 | " \n", 664 | " \n", 665 | " \n", 666 | " \n", 667 | " \n", 668 | " \n", 669 | " \n", 670 | " \n", 671 | " \n", 672 | " \n", 673 | " \n", 674 | " \n", 675 | " \n", 676 | " \n", 677 | " \n", 678 | " \n", 679 | " \n", 680 | " \n", 681 | " \n", 682 | " \n", 683 | " \n", 684 | " \n", 685 | " \n", 686 | " \n", 687 | " \n", 688 | " \n", 689 | " \n", 690 | " \n", 691 | " \n", 692 | " \n", 693 | " \n", 694 | " \n", 695 | " \n", 696 | " \n", 697 | " \n", 698 | " \n", 699 | " \n", 700 | " \n", 701 | " \n", 702 | " \n", 703 | " \n", 704 | " \n", 705 | " \n", 706 | " \n", 707 | " \n", 708 | " \n", 709 | " \n", 710 | " \n", 711 | " \n", 712 | " \n", 713 | " \n", 714 | " \n", 715 | " \n", 716 | " \n", 717 | " \n", 718 | " \n", 719 | " \n", 720 | " \n", 721 | " \n", 722 | " \n", 723 | " \n", 724 | " \n", 725 | " \n", 726 | " \n", 727 | " \n", 728 | " \n", 729 | " \n", 730 | " \n", 731 | " \n", 732 | " \n", 733 | " \n", 734 | " \n", 735 | " \n", 736 | " \n", 737 | " \n", 738 | " \n", 739 | " \n", 740 | " \n", 741 | " \n", 742 | " \n", 743 | " \n", 744 | " \n", 745 | " \n", 746 | " \n", 747 | " \n", 748 | " \n", 749 | " \n", 750 | " \n", 751 | " \n", 752 | " \n", 753 | " \n", 754 | " \n", 755 | " \n", 756 | " \n", 757 | " \n", 758 | " \n", 759 | " \n", 760 | " \n", 761 | " \n", 762 | " \n", 763 | " \n", 764 | " \n", 765 | " \n", 766 | " \n", 767 | " \n", 768 | " \n", 769 | " \n", 770 | " \n", 771 | " \n", 772 | " \n", 773 | " \n", 774 | " \n", 775 | " \n", 776 | " \n", 777 | " \n", 778 | " \n", 779 | " \n", 780 | " \n", 781 | " \n", 782 | " \n", 783 | " \n", 784 | " \n", 785 | " \n", 786 | " \n", 787 | " \n", 788 | " \n", 789 | " \n", 790 | " \n", 791 | " \n", 792 | " \n", 793 | " \n", 794 | " \n", 795 | " \n", 796 | " \n", 797 | " \n", 798 | " \n", 799 | " \n", 800 | " \n", 801 | " \n", 802 | " \n", 803 | " \n", 804 | " \n", 805 | " \n", 806 | " \n", 807 | " \n", 808 | " \n", 809 | " \n", 810 | " \n", 811 | " \n", 812 | " \n", 813 | " \n", 814 | " \n", 815 | " \n", 816 | " \n", 817 | " \n", 818 | " \n", 819 | " \n", 820 | " \n", 821 | " \n", 822 | " \n", 823 | " \n", 824 | " \n", 825 | " \n", 826 | " \n", 827 | " \n", 828 | " \n", 829 | " \n", 830 | " \n", 831 | " \n", 832 | " \n", 833 | " \n", 834 | " \n", 835 | " \n", 836 | " \n", 837 | " \n", 838 | " \n", 839 | "
mpgcyldisphpdratwtqsecvsamgearcarb
Mazda RX421.06.0160.0110.03.902.62016.460.01.04.04.0
Mazda RX4 Wag21.06.0160.0110.03.902.87517.020.01.04.04.0
Datsun 71022.84.0108.093.03.852.32018.611.01.04.01.0
Hornet 4 Drive21.46.0258.0110.03.083.21519.441.00.03.01.0
Hornet Sportabout18.78.0360.0175.03.153.44017.020.00.03.02.0
Valiant18.16.0225.0105.02.763.46020.221.00.03.01.0
Duster 36014.38.0360.0245.03.213.57015.840.00.03.04.0
Merc 240D24.44.0146.762.03.693.19020.001.00.04.02.0
Merc 23022.84.0140.895.03.923.15022.901.00.04.02.0
Merc 28019.26.0167.6123.03.923.44018.301.00.04.04.0
Merc 280C17.86.0167.6123.03.923.44018.901.00.04.04.0
Merc 450SE16.48.0275.8180.03.074.07017.400.00.03.03.0
Merc 450SL17.38.0275.8180.03.073.73017.600.00.03.03.0
Merc 450SLC15.28.0275.8180.03.073.78018.000.00.03.03.0
Cadillac Fleetwood10.48.0472.0205.02.935.25017.980.00.03.04.0
Lincoln Continental10.48.0460.0215.03.005.42417.820.00.03.04.0
Chrysler Imperial14.78.0440.0230.03.235.34517.420.00.03.04.0
Fiat 12832.44.078.766.04.082.20019.471.01.04.01.0
Honda Civic30.44.075.752.04.931.61518.521.01.04.02.0
Toyota Corolla33.94.071.165.04.221.83519.901.01.04.01.0
Toyota Corona21.54.0120.197.03.702.46520.011.00.03.01.0
Dodge Challenger15.58.0318.0150.02.763.52016.870.00.03.02.0
AMC Javelin15.28.0304.0150.03.153.43517.300.00.03.02.0
Camaro Z2813.38.0350.0245.03.733.84015.410.00.03.04.0
Pontiac Firebird19.28.0400.0175.03.083.84517.050.00.03.02.0
Fiat X1-927.34.079.066.04.081.93518.901.01.04.01.0
Porsche 914-226.04.0120.391.04.432.14016.700.01.05.02.0
Lotus Europa30.44.095.1113.03.771.51316.901.01.05.02.0
Ford Pantera L15.88.0351.0264.04.223.17014.500.01.05.04.0
Ferrari Dino19.76.0145.0175.03.622.77015.500.01.05.06.0
Maserati Bora15.08.0301.0335.03.543.57014.600.01.05.08.0
Volvo 142E21.44.0121.0109.04.112.78018.601.01.04.02.0
\n", 840 | "
" 841 | ], 842 | "text/plain": [ 843 | " mpg cyl disp hp drat wt qsec vs am gear carb\n", 844 | "Mazda RX4 21.0 6.0 160.0 110.0 3.90 2.620 16.46 0.0 1.0 4.0 4.0\n", 845 | "Mazda RX4 Wag 21.0 6.0 160.0 110.0 3.90 2.875 17.02 0.0 1.0 4.0 4.0\n", 846 | "Datsun 710 22.8 4.0 108.0 93.0 3.85 2.320 18.61 1.0 1.0 4.0 1.0\n", 847 | "Hornet 4 Drive 21.4 6.0 258.0 110.0 3.08 3.215 19.44 1.0 0.0 3.0 1.0\n", 848 | "Hornet Sportabout 18.7 8.0 360.0 175.0 3.15 3.440 17.02 0.0 0.0 3.0 2.0\n", 849 | "Valiant 18.1 6.0 225.0 105.0 2.76 3.460 20.22 1.0 0.0 3.0 1.0\n", 850 | "Duster 360 14.3 8.0 360.0 245.0 3.21 3.570 15.84 0.0 0.0 3.0 4.0\n", 851 | "Merc 240D 24.4 4.0 146.7 62.0 3.69 3.190 20.00 1.0 0.0 4.0 2.0\n", 852 | "Merc 230 22.8 4.0 140.8 95.0 3.92 3.150 22.90 1.0 0.0 4.0 2.0\n", 853 | "Merc 280 19.2 6.0 167.6 123.0 3.92 3.440 18.30 1.0 0.0 4.0 4.0\n", 854 | "Merc 280C 17.8 6.0 167.6 123.0 3.92 3.440 18.90 1.0 0.0 4.0 4.0\n", 855 | "Merc 450SE 16.4 8.0 275.8 180.0 3.07 4.070 17.40 0.0 0.0 3.0 3.0\n", 856 | "Merc 450SL 17.3 8.0 275.8 180.0 3.07 3.730 17.60 0.0 0.0 3.0 3.0\n", 857 | "Merc 450SLC 15.2 8.0 275.8 180.0 3.07 3.780 18.00 0.0 0.0 3.0 3.0\n", 858 | "Cadillac Fleetwood 10.4 8.0 472.0 205.0 2.93 5.250 17.98 0.0 0.0 3.0 4.0\n", 859 | "Lincoln Continental 10.4 8.0 460.0 215.0 3.00 5.424 17.82 0.0 0.0 3.0 4.0\n", 860 | "Chrysler Imperial 14.7 8.0 440.0 230.0 3.23 5.345 17.42 0.0 0.0 3.0 4.0\n", 861 | "Fiat 128 32.4 4.0 78.7 66.0 4.08 2.200 19.47 1.0 1.0 4.0 1.0\n", 862 | "Honda Civic 30.4 4.0 75.7 52.0 4.93 1.615 18.52 1.0 1.0 4.0 2.0\n", 863 | "Toyota Corolla 33.9 4.0 71.1 65.0 4.22 1.835 19.90 1.0 1.0 4.0 1.0\n", 864 | "Toyota Corona 21.5 4.0 120.1 97.0 3.70 2.465 20.01 1.0 0.0 3.0 1.0\n", 865 | "Dodge Challenger 15.5 8.0 318.0 150.0 2.76 3.520 16.87 0.0 0.0 3.0 2.0\n", 866 | "AMC Javelin 15.2 8.0 304.0 150.0 3.15 3.435 17.30 0.0 0.0 3.0 2.0\n", 867 | "Camaro Z28 13.3 8.0 350.0 245.0 3.73 3.840 15.41 0.0 0.0 3.0 4.0\n", 868 | "Pontiac Firebird 19.2 8.0 400.0 175.0 3.08 3.845 17.05 0.0 0.0 3.0 2.0\n", 869 | "Fiat X1-9 27.3 4.0 79.0 66.0 4.08 1.935 18.90 1.0 1.0 4.0 1.0\n", 870 | "Porsche 914-2 26.0 4.0 120.3 91.0 4.43 2.140 16.70 0.0 1.0 5.0 2.0\n", 871 | "Lotus Europa 30.4 4.0 95.1 113.0 3.77 1.513 16.90 1.0 1.0 5.0 2.0\n", 872 | "Ford Pantera L 15.8 8.0 351.0 264.0 4.22 3.170 14.50 0.0 1.0 5.0 4.0\n", 873 | "Ferrari Dino 19.7 6.0 145.0 175.0 3.62 2.770 15.50 0.0 1.0 5.0 6.0\n", 874 | "Maserati Bora 15.0 8.0 301.0 335.0 3.54 3.570 14.60 0.0 1.0 5.0 8.0\n", 875 | "Volvo 142E 21.4 4.0 121.0 109.0 4.11 2.780 18.60 1.0 1.0 4.0 2.0" 876 | ] 877 | }, 878 | "execution_count": 17, 879 | "metadata": {}, 880 | "output_type": "execute_result" 881 | } 882 | ], 883 | "source": [ 884 | "%get mtcars --from R\n", 885 | "mtcars" 886 | ] 887 | }, 888 | { 889 | "cell_type": "code", 890 | "execution_count": 18, 891 | "metadata": { 892 | "kernel": "SoS", 893 | "scrolled": false 894 | }, 895 | "outputs": [ 896 | { 897 | "data": { 898 | "text/html": [ 899 | "

SoS

\n", 900 | "\n", 901 | "\n", 902 | "\n", 903 | "\n", 904 | "
SoS Version
0.9.16.8
\n", 905 | "

R

\n", 906 | "\n", 907 | "\n", 908 | "\n", 909 | "\n", 910 | "\n", 911 | "\n", 912 | "\n", 913 | "\n", 914 | "\n", 937 | "\n", 938 | "
Kernel
ir
Language
R
R version 3.5.0 (2018-04-23)\n",
915 |        "Platform: x86_64-apple-darwin13.4.0 (64-bit)\n",
916 |        "Running under: macOS Sierra 10.12.5\n",
917 |        "\n",
918 |        "Matrix products: default\n",
919 |        "BLAS/LAPACK: /Users/bpeng1/anaconda3/envs/JupyterCon18/lib/libopenblasp-r0.2.20.dylib\n",
920 |        "\n",
921 |        "locale:\n",
922 |        "[1] en_US.UTF-8/en_US.UTF-8/en_US.UTF-8/C/en_US.UTF-8/en_US.UTF-8\n",
923 |        "\n",
924 |        "attached base packages:\n",
925 |        "[1] stats     graphics  grDevices utils     datasets  methods   base     \n",
926 |        "\n",
927 |        "other attached packages:\n",
928 |        "[1] feather_0.3.1\n",
929 |        "\n",
930 |        "loaded via a namespace (and not attached):\n",
931 |        " [1] Rcpp_0.12.18    digest_0.6.15   crayon_1.3.4    IRdisplay_0.5.0\n",
932 |        " [5] repr_0.15.0     jsonlite_1.5    magrittr_1.5    evaluate_0.11  \n",
933 |        " [9] pillar_1.3.0    rlang_0.2.2     stringi_1.2.4   uuid_0.1-2     \n",
934 |        "[13] IRkernel_0.8.11 tools_3.5.0     stringr_1.3.1   hms_0.4.2      \n",
935 |        "[17] compiler_3.5.0  pkgconfig_2.0.2 base64enc_0.1-3 htmltools_0.3.6\n",
936 |        "[21] pbdZMQ_0.3-3    tibble_1.4.2   
\n" 939 | ] 940 | }, 941 | "metadata": {}, 942 | "output_type": "display_data" 943 | } 944 | ], 945 | "source": [ 946 | "%sessioninfo" 947 | ] 948 | } 949 | ], 950 | "metadata": { 951 | "kernelspec": { 952 | "display_name": "SoS", 953 | "language": "sos", 954 | "name": "sos" 955 | }, 956 | "language_info": { 957 | "codemirror_mode": "sos", 958 | "file_extension": ".sos", 959 | "mimetype": "text/x-sos", 960 | "name": "sos", 961 | "nbconvert_exporter": "sos_notebook.converter.SoS_Exporter", 962 | "pygments_lexer": "sos" 963 | }, 964 | "sos": { 965 | "kernels": [ 966 | [ 967 | "R", 968 | "ir", 969 | "R", 970 | "#DCDCDA" 971 | ], 972 | [ 973 | "SoS", 974 | "sos", 975 | "", 976 | "" 977 | ] 978 | ], 979 | "panel": { 980 | "displayed": true, 981 | "height": 0, 982 | "style": "side" 983 | }, 984 | "version": "0.9.16.7" 985 | } 986 | }, 987 | "nbformat": 4, 988 | "nbformat_minor": 2 989 | } 990 | -------------------------------------------------------------------------------- /3_SoS_Magics.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": { 6 | "kernel": "SoS" 7 | }, 8 | "source": [ 9 | "# SoS Magics (Preview, session, and report)" 10 | ] 11 | }, 12 | { 13 | "cell_type": "code", 14 | "execution_count": 1, 15 | "metadata": { 16 | "kernel": "SoS", 17 | "tags": [ 18 | "report_output" 19 | ] 20 | }, 21 | "outputs": [ 22 | { 23 | "data": { 24 | "text/html": [ 25 | "\n", 26 | " \n", 27 | " \n", 28 | " \n", 29 | " \n", 30 | " \n", 31 | " \n", 32 | " \n", 33 | " \n", 34 | "\n", 35 | "\n", 36 | "\n", 37 | "\n", 38 | "\n", 39 | "\n", 40 | "\n", 41 | "\n", 42 | "\n", 43 | "\n", 44 | "\n", 45 | "\n", 46 | "\n", 47 | "\n", 48 | "
RevisionAuthorDateMessage
514e219Bo Peng2018-08-21Update notebooks
4a06c81Bo Peng2018-08-18Update figures
6bc69eeBo Peng2018-08-18Update magics noterbook and slides
b625104Bo Peng2018-08-17Complete preview magic
cfa7fb1Bo Peng2018-08-16Add skeleton of examples
" 49 | ] 50 | }, 51 | "metadata": {}, 52 | "output_type": "display_data" 53 | } 54 | ], 55 | "source": [ 56 | "%revisions" 57 | ] 58 | }, 59 | { 60 | "cell_type": "markdown", 61 | "metadata": { 62 | "kernel": "SoS" 63 | }, 64 | "source": [ 65 | "## `%preview`" 66 | ] 67 | }, 68 | { 69 | "cell_type": "code", 70 | "execution_count": 2, 71 | "metadata": { 72 | "kernel": "SoS" 73 | }, 74 | "outputs": [ 75 | { 76 | "name": "stderr", 77 | "output_type": "stream", 78 | "text": [ 79 | "Loading required package: feather\n" 80 | ] 81 | } 82 | ], 83 | "source": [ 84 | "%preview mtcars\n", 85 | "%get mtcars --from R" 86 | ] 87 | }, 88 | { 89 | "cell_type": "code", 90 | "execution_count": 3, 91 | "metadata": { 92 | "kernel": "R", 93 | "tags": [ 94 | "report_output" 95 | ] 96 | }, 97 | "outputs": [ 98 | { 99 | "data": { 100 | "text/html": [ 101 | "pdf: 2" 102 | ], 103 | "text/latex": [ 104 | "\\textbf{pdf:} 2" 105 | ], 106 | "text/markdown": [ 107 | "**pdf:** 2" 108 | ], 109 | "text/plain": [ 110 | "pdf \n", 111 | " 2 " 112 | ] 113 | }, 114 | "metadata": {}, 115 | "output_type": "display_data" 116 | }, 117 | { 118 | "data": { 119 | "text/html": [ 120 | "
%preview scatterplot.png
" 121 | ] 122 | }, 123 | "metadata": {}, 124 | "output_type": "display_data" 125 | }, 126 | { 127 | "data": { 128 | "text/html": [ 129 | "
> scatterplot.png (17.9 KiB):
" 130 | ], 131 | "text/plain": [ 132 | "\n", 133 | "> scatterplot.png (17.9 KiB):" 134 | ] 135 | }, 136 | "metadata": {}, 137 | "output_type": "display_data" 138 | }, 139 | { 140 | "data": { 141 | "image/png": "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" 142 | }, 143 | "metadata": {}, 144 | "output_type": "display_data" 145 | } 146 | ], 147 | "source": [ 148 | "%preview -n scatterplot.png\n", 149 | "png('scatterplot.png', width=500, height=300)\n", 150 | "plot(mtcars$wt, mtcars$mpg, main=\"Scatterplot of mtcars\", \n", 151 | " xlab=\"Car Weight\", ylab=\"Miles Per Gallon \")\n", 152 | "dev.off()" 153 | ] 154 | }, 155 | { 156 | "cell_type": "code", 157 | "execution_count": 4, 158 | "metadata": { 159 | "kernel": "JavaScript" 160 | }, 161 | "outputs": [ 162 | { 163 | "data": { 164 | "text/plain": [ 165 | "{ 'Mazda RX4': \n", 166 | " { mpg: 21,\n", 167 | " cyl: 6,\n", 168 | " disp: 160,\n", 169 | " hp: 110,\n", 170 | " drat: 3.9,\n", 171 | " wt: 2.62,\n", 172 | " qsec: 16.46,\n", 173 | " vs: 0,\n", 174 | " am: 1,\n", 175 | " gear: 4,\n", 176 | " carb: 4 },\n", 177 | " 'Mazda RX4 Wag': \n", 178 | " { mpg: 21,\n", 179 | " cyl: 6,\n", 180 | " disp: 160,\n", 181 | " hp: 110,\n", 182 | " drat: 3.9,\n", 183 | " wt: 2.875,\n", 184 | " qsec: 17.02,\n", 185 | " vs: 0,\n", 186 | " am: 1,\n", 187 | " gear: 4,\n", 188 | " carb: 4 },\n", 189 | " 'Datsun 710': \n", 190 | " { mpg: 22.8,\n", 191 | " cyl: 4,\n", 192 | " disp: 108,\n", 193 | " hp: 93,\n", 194 | " drat: 3.85,\n", 195 | " wt: 2.32,\n", 196 | " qsec: 18.61,\n", 197 | " vs: 1,\n", 198 | " am: 1,\n", 199 | " gear: 4,\n", 200 | " carb: 1 },\n", 201 | " 'Hornet 4 Drive': \n", 202 | " { mpg: 21.4,\n", 203 | " cyl: 6,\n", 204 | " disp: 258,\n", 205 | " hp: 110,\n", 206 | " drat: 3.08,\n", 207 | " wt: 3.215,\n", 208 | " qsec: 19.44,\n", 209 | " vs: 1,\n", 210 | " am: 0,\n", 211 | " gear: 3,\n", 212 | " carb: 1 },\n", 213 | " 'Hornet Sportabout': \n", 214 | " { mpg: 18.7,\n", 215 | " cyl: 8,\n", 216 | " disp: 360,\n", 217 | " hp: 175,\n", 218 | " drat: 3.15,\n", 219 | " wt: 3.44,\n", 220 | " qsec: 17.02,\n", 221 | " vs: 0,\n", 222 | " am: 0,\n", 223 | " gear: 3,\n", 224 | " carb: 2 },\n", 225 | " Valiant: \n", 226 | " { mpg: 18.1,\n", 227 | " cyl: 6,\n", 228 | " disp: 225,\n", 229 | " hp: 105,\n", 230 | " drat: 2.76,\n", 231 | " wt: 3.46,\n", 232 | " qsec: 20.22,\n", 233 | " vs: 1,\n", 234 | " am: 0,\n", 235 | " gear: 3,\n", 236 | " carb: 1 },\n", 237 | " 'Duster 360': \n", 238 | " { mpg: 14.3,\n", 239 | " cyl: 8,\n", 240 | " disp: 360,\n", 241 | " hp: 245,\n", 242 | " drat: 3.21,\n", 243 | " wt: 3.57,\n", 244 | " qsec: 15.84,\n", 245 | " vs: 0,\n", 246 | " am: 0,\n", 247 | " gear: 3,\n", 248 | " carb: 4 },\n", 249 | " 'Merc 240D': \n", 250 | " { mpg: 24.4,\n", 251 | " cyl: 4,\n", 252 | " disp: 146.7,\n", 253 | " hp: 62,\n", 254 | " drat: 3.69,\n", 255 | " wt: 3.19,\n", 256 | " qsec: 20,\n", 257 | " vs: 1,\n", 258 | " am: 0,\n", 259 | " gear: 4,\n", 260 | " carb: 2 },\n", 261 | " 'Merc 230': \n", 262 | " { mpg: 22.8,\n", 263 | " cyl: 4,\n", 264 | " disp: 140.8,\n", 265 | " hp: 95,\n", 266 | " drat: 3.92,\n", 267 | " wt: 3.15,\n", 268 | " qsec: 22.9,\n", 269 | " vs: 1,\n", 270 | " am: 0,\n", 271 | " gear: 4,\n", 272 | " carb: 2 },\n", 273 | " 'Merc 280': \n", 274 | " { mpg: 19.2,\n", 275 | " cyl: 6,\n", 276 | " disp: 167.6,\n", 277 | " hp: 123,\n", 278 | " drat: 3.92,\n", 279 | " wt: 3.44,\n", 280 | " qsec: 18.3,\n", 281 | " vs: 1,\n", 282 | " am: 0,\n", 283 | " gear: 4,\n", 284 | " carb: 4 },\n", 285 | " 'Merc 280C': \n", 286 | " { mpg: 17.8,\n", 287 | " cyl: 6,\n", 288 | " disp: 167.6,\n", 289 | " hp: 123,\n", 290 | " drat: 3.92,\n", 291 | " wt: 3.44,\n", 292 | " qsec: 18.9,\n", 293 | " vs: 1,\n", 294 | " am: 0,\n", 295 | " gear: 4,\n", 296 | " carb: 4 },\n", 297 | " 'Merc 450SE': \n", 298 | " { mpg: 16.4,\n", 299 | " cyl: 8,\n", 300 | " disp: 275.8,\n", 301 | " hp: 180,\n", 302 | " drat: 3.07,\n", 303 | " wt: 4.07,\n", 304 | " qsec: 17.4,\n", 305 | " vs: 0,\n", 306 | " am: 0,\n", 307 | " gear: 3,\n", 308 | " carb: 3 },\n", 309 | " 'Merc 450SL': \n", 310 | " { mpg: 17.3,\n", 311 | " cyl: 8,\n", 312 | " disp: 275.8,\n", 313 | " hp: 180,\n", 314 | " drat: 3.07,\n", 315 | " wt: 3.73,\n", 316 | " qsec: 17.6,\n", 317 | " vs: 0,\n", 318 | " am: 0,\n", 319 | " gear: 3,\n", 320 | " carb: 3 },\n", 321 | " 'Merc 450SLC': \n", 322 | " { mpg: 15.2,\n", 323 | " cyl: 8,\n", 324 | " disp: 275.8,\n", 325 | " hp: 180,\n", 326 | " drat: 3.07,\n", 327 | " wt: 3.78,\n", 328 | " qsec: 18,\n", 329 | " vs: 0,\n", 330 | " am: 0,\n", 331 | " gear: 3,\n", 332 | " carb: 3 },\n", 333 | " 'Cadillac Fleetwood': \n", 334 | " { mpg: 10.4,\n", 335 | " cyl: 8,\n", 336 | " disp: 472,\n", 337 | " hp: 205,\n", 338 | " drat: 2.93,\n", 339 | " wt: 5.25,\n", 340 | " qsec: 17.98,\n", 341 | " vs: 0,\n", 342 | " am: 0,\n", 343 | " gear: 3,\n", 344 | " carb: 4 },\n", 345 | " 'Lincoln Continental': \n", 346 | " { mpg: 10.4,\n", 347 | " cyl: 8,\n", 348 | " disp: 460,\n", 349 | " hp: 215,\n", 350 | " drat: 3,\n", 351 | " wt: 5.424,\n", 352 | " qsec: 17.82,\n", 353 | " vs: 0,\n", 354 | " am: 0,\n", 355 | " gear: 3,\n", 356 | " carb: 4 },\n", 357 | " 'Chrysler Imperial': \n", 358 | " { mpg: 14.7,\n", 359 | " cyl: 8,\n", 360 | " disp: 440,\n", 361 | " hp: 230,\n", 362 | " drat: 3.23,\n", 363 | " wt: 5.345,\n", 364 | " qsec: 17.42,\n", 365 | " vs: 0,\n", 366 | " am: 0,\n", 367 | " gear: 3,\n", 368 | " carb: 4 },\n", 369 | " 'Fiat 128': \n", 370 | " { mpg: 32.4,\n", 371 | " cyl: 4,\n", 372 | " disp: 78.7,\n", 373 | " hp: 66,\n", 374 | " drat: 4.08,\n", 375 | " wt: 2.2,\n", 376 | " qsec: 19.47,\n", 377 | " vs: 1,\n", 378 | " am: 1,\n", 379 | " gear: 4,\n", 380 | " carb: 1 },\n", 381 | " 'Honda Civic': \n", 382 | " { mpg: 30.4,\n", 383 | " cyl: 4,\n", 384 | " disp: 75.7,\n", 385 | " hp: 52,\n", 386 | " drat: 4.93,\n", 387 | " wt: 1.615,\n", 388 | " qsec: 18.52,\n", 389 | " vs: 1,\n", 390 | " am: 1,\n", 391 | " gear: 4,\n", 392 | " carb: 2 },\n", 393 | " 'Toyota Corolla': \n", 394 | " { mpg: 33.9,\n", 395 | " cyl: 4,\n", 396 | " disp: 71.1,\n", 397 | " hp: 65,\n", 398 | " drat: 4.22,\n", 399 | " wt: 1.835,\n", 400 | " qsec: 19.9,\n", 401 | " vs: 1,\n", 402 | " am: 1,\n", 403 | " gear: 4,\n", 404 | " carb: 1 },\n", 405 | " 'Toyota Corona': \n", 406 | " { mpg: 21.5,\n", 407 | " cyl: 4,\n", 408 | " disp: 120.1,\n", 409 | " hp: 97,\n", 410 | " drat: 3.7,\n", 411 | " wt: 2.465,\n", 412 | " qsec: 20.01,\n", 413 | " vs: 1,\n", 414 | " am: 0,\n", 415 | " gear: 3,\n", 416 | " carb: 1 },\n", 417 | " 'Dodge Challenger': \n", 418 | " { mpg: 15.5,\n", 419 | " cyl: 8,\n", 420 | " disp: 318,\n", 421 | " hp: 150,\n", 422 | " drat: 2.76,\n", 423 | " wt: 3.52,\n", 424 | " qsec: 16.87,\n", 425 | " vs: 0,\n", 426 | " am: 0,\n", 427 | " gear: 3,\n", 428 | " carb: 2 },\n", 429 | " 'AMC Javelin': \n", 430 | " { mpg: 15.2,\n", 431 | " cyl: 8,\n", 432 | " disp: 304,\n", 433 | " hp: 150,\n", 434 | " drat: 3.15,\n", 435 | " wt: 3.435,\n", 436 | " qsec: 17.3,\n", 437 | " vs: 0,\n", 438 | " am: 0,\n", 439 | " gear: 3,\n", 440 | " carb: 2 },\n", 441 | " 'Camaro Z28': \n", 442 | " { mpg: 13.3,\n", 443 | " cyl: 8,\n", 444 | " disp: 350,\n", 445 | " hp: 245,\n", 446 | " drat: 3.73,\n", 447 | " wt: 3.84,\n", 448 | " qsec: 15.41,\n", 449 | " vs: 0,\n", 450 | " am: 0,\n", 451 | " gear: 3,\n", 452 | " carb: 4 },\n", 453 | " 'Pontiac Firebird': \n", 454 | " { mpg: 19.2,\n", 455 | " cyl: 8,\n", 456 | " disp: 400,\n", 457 | " hp: 175,\n", 458 | " drat: 3.08,\n", 459 | " wt: 3.845,\n", 460 | " qsec: 17.05,\n", 461 | " vs: 0,\n", 462 | " am: 0,\n", 463 | " gear: 3,\n", 464 | " carb: 2 },\n", 465 | " 'Fiat X1-9': \n", 466 | " { mpg: 27.3,\n", 467 | " cyl: 4,\n", 468 | " disp: 79,\n", 469 | " hp: 66,\n", 470 | " drat: 4.08,\n", 471 | " wt: 1.935,\n", 472 | " qsec: 18.9,\n", 473 | " vs: 1,\n", 474 | " am: 1,\n", 475 | " gear: 4,\n", 476 | " carb: 1 },\n", 477 | " 'Porsche 914-2': \n", 478 | " { mpg: 26,\n", 479 | " cyl: 4,\n", 480 | " disp: 120.3,\n", 481 | " hp: 91,\n", 482 | " drat: 4.43,\n", 483 | " wt: 2.14,\n", 484 | " qsec: 16.7,\n", 485 | " vs: 0,\n", 486 | " am: 1,\n", 487 | " gear: 5,\n", 488 | " carb: 2 },\n", 489 | " 'Lotus Europa': \n", 490 | " { mpg: 30.4,\n", 491 | " cyl: 4,\n", 492 | " disp: 95.1,\n", 493 | " hp: 113,\n", 494 | " drat: 3.77,\n", 495 | " wt: 1.513,\n", 496 | " qsec: 16.9,\n", 497 | " vs: 1,\n", 498 | " am: 1,\n", 499 | " gear: 5,\n", 500 | " carb: 2 },\n", 501 | " 'Ford Pantera L': \n", 502 | " { mpg: 15.8,\n", 503 | " cyl: 8,\n", 504 | " disp: 351,\n", 505 | " hp: 264,\n", 506 | " drat: 4.22,\n", 507 | " wt: 3.17,\n", 508 | " qsec: 14.5,\n", 509 | " vs: 0,\n", 510 | " am: 1,\n", 511 | " gear: 5,\n", 512 | " carb: 4 },\n", 513 | " 'Ferrari Dino': \n", 514 | " { mpg: 19.7,\n", 515 | " cyl: 6,\n", 516 | " disp: 145,\n", 517 | " hp: 175,\n", 518 | " drat: 3.62,\n", 519 | " wt: 2.77,\n", 520 | " qsec: 15.5,\n", 521 | " vs: 0,\n", 522 | " am: 1,\n", 523 | " gear: 5,\n", 524 | " carb: 6 },\n", 525 | " 'Maserati Bora': \n", 526 | " { mpg: 15,\n", 527 | " cyl: 8,\n", 528 | " disp: 301,\n", 529 | " hp: 335,\n", 530 | " drat: 3.54,\n", 531 | " wt: 3.57,\n", 532 | " qsec: 14.6,\n", 533 | " vs: 0,\n", 534 | " am: 1,\n", 535 | " gear: 5,\n", 536 | " carb: 8 },\n", 537 | " 'Volvo 142E': \n", 538 | " { mpg: 21.4,\n", 539 | " cyl: 4,\n", 540 | " disp: 121,\n", 541 | " hp: 109,\n", 542 | " drat: 4.11,\n", 543 | " wt: 2.78,\n", 544 | " qsec: 18.6,\n", 545 | " vs: 1,\n", 546 | " am: 1,\n", 547 | " gear: 4,\n", 548 | " carb: 2 } }" 549 | ] 550 | }, 551 | "execution_count": 4, 552 | "metadata": {}, 553 | "output_type": "execute_result" 554 | } 555 | ], 556 | "source": [ 557 | "%get mtcars --from R\n", 558 | "mtcars" 559 | ] 560 | }, 561 | { 562 | "cell_type": "markdown", 563 | "metadata": { 564 | "kernel": "SoS" 565 | }, 566 | "source": [ 567 | "## `%sessioninfo`" 568 | ] 569 | }, 570 | { 571 | "cell_type": "code", 572 | "execution_count": 5, 573 | "metadata": { 574 | "kernel": "SoS", 575 | "tags": [ 576 | "report_output" 577 | ] 578 | }, 579 | "outputs": [ 580 | { 581 | "data": { 582 | "text/html": [ 583 | "

SoS

\n", 584 | "\n", 585 | "\n", 586 | "\n", 587 | "\n", 588 | "
SoS Version
0.9.16.8
\n", 589 | "

R

\n", 590 | "\n", 591 | "\n", 592 | "\n", 593 | "\n", 594 | "\n", 595 | "\n", 596 | "\n", 597 | "\n", 598 | "\n", 621 | "\n", 622 | "
Kernel
ir
Language
R
R version 3.5.0 (2018-04-23)\n",
599 |        "Platform: x86_64-apple-darwin13.4.0 (64-bit)\n",
600 |        "Running under: macOS Sierra 10.12.5\n",
601 |        "\n",
602 |        "Matrix products: default\n",
603 |        "BLAS/LAPACK: /Users/bpeng1/anaconda3/envs/JupyterCon18/lib/libopenblasp-r0.2.20.dylib\n",
604 |        "\n",
605 |        "locale:\n",
606 |        "[1] en_US.UTF-8/en_US.UTF-8/en_US.UTF-8/C/en_US.UTF-8/en_US.UTF-8\n",
607 |        "\n",
608 |        "attached base packages:\n",
609 |        "[1] stats     graphics  grDevices utils     datasets  methods   base     \n",
610 |        "\n",
611 |        "other attached packages:\n",
612 |        "[1] feather_0.3.1\n",
613 |        "\n",
614 |        "loaded via a namespace (and not attached):\n",
615 |        " [1] Rcpp_0.12.18    digest_0.6.15   crayon_1.3.4    IRdisplay_0.5.0\n",
616 |        " [5] repr_0.15.0     jsonlite_1.5    magrittr_1.5    evaluate_0.11  \n",
617 |        " [9] pillar_1.3.0    rlang_0.2.2     stringi_1.2.4   uuid_0.1-2     \n",
618 |        "[13] IRkernel_0.8.11 tools_3.5.0     stringr_1.3.1   hms_0.4.2      \n",
619 |        "[17] compiler_3.5.0  pkgconfig_2.0.2 base64enc_0.1-3 htmltools_0.3.6\n",
620 |        "[21] pbdZMQ_0.3-3    tibble_1.4.2   
\n", 623 | "

JavaScript

\n", 624 | "\n", 625 | "\n", 626 | "\n", 627 | "\n", 628 | "\n", 629 | "\n", 630 | "\n", 631 | "
Kernel
javascript
Language
JavaScript
\n" 632 | ] 633 | }, 634 | "metadata": {}, 635 | "output_type": "display_data" 636 | } 637 | ], 638 | "source": [ 639 | "%sessioninfo" 640 | ] 641 | }, 642 | { 643 | "cell_type": "markdown", 644 | "metadata": { 645 | "kernel": "SoS" 646 | }, 647 | "source": [ 648 | "## `%sossave`" 649 | ] 650 | }, 651 | { 652 | "cell_type": "code", 653 | "execution_count": 6, 654 | "metadata": { 655 | "kernel": "SoS" 656 | }, 657 | "outputs": [ 658 | { 659 | "data": { 660 | "text/html": [ 661 | "
Workflow saved to 3_SoS_Magics.html
" 662 | ], 663 | "text/plain": [ 664 | "Workflow saved to 3_SoS_Magics.html\n" 665 | ] 666 | }, 667 | "metadata": {}, 668 | "output_type": "display_data" 669 | } 670 | ], 671 | "source": [ 672 | "%sossave --to html --force" 673 | ] 674 | } 675 | ], 676 | "metadata": { 677 | "kernelspec": { 678 | "display_name": "SoS", 679 | "language": "sos", 680 | "name": "sos" 681 | }, 682 | "language_info": { 683 | "codemirror_mode": "sos", 684 | "file_extension": ".sos", 685 | "mimetype": "text/x-sos", 686 | "name": "sos", 687 | "nbconvert_exporter": "sos_notebook.converter.SoS_Exporter", 688 | "pygments_lexer": "sos" 689 | }, 690 | "sos": { 691 | "kernels": [], 692 | "panel": { 693 | "displayed": true, 694 | "height": 0, 695 | "style": "side" 696 | }, 697 | "version": "0.9.16.7" 698 | } 699 | }, 700 | "nbformat": 4, 701 | "nbformat_minor": 2 702 | } 703 | -------------------------------------------------------------------------------- /4_Notebook_to_Workflow.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": { 6 | "kernel": "SoS" 7 | }, 8 | "source": [ 9 | "## Creation of a SoS workflow from interactive analysis" 10 | ] 11 | }, 12 | { 13 | "cell_type": "markdown", 14 | "metadata": { 15 | "kernel": "SoS" 16 | }, 17 | "source": [ 18 | "## Basic Syntax" 19 | ] 20 | }, 21 | { 22 | "cell_type": "markdown", 23 | "metadata": { 24 | "kernel": "SoS" 25 | }, 26 | "source": [ 27 | "### Script format of function calls" 28 | ] 29 | }, 30 | { 31 | "cell_type": "code", 32 | "execution_count": 1, 33 | "metadata": { 34 | "kernel": "SoS" 35 | }, 36 | "outputs": [], 37 | "source": [ 38 | "res_file = 'test.pdf'" 39 | ] 40 | }, 41 | { 42 | "cell_type": "code", 43 | "execution_count": 2, 44 | "metadata": { 45 | "kernel": "SoS" 46 | }, 47 | "outputs": [ 48 | { 49 | "name": "stdout", 50 | "output_type": "stream", 51 | "text": [ 52 | "null device \n", 53 | " 1 \n" 54 | ] 55 | } 56 | ], 57 | "source": [ 58 | "R(f'''\n", 59 | "pdf('{res_file}')\n", 60 | "plot(0, 0)\n", 61 | "dev.off()\n", 62 | "''', workdir='result')" 63 | ] 64 | }, 65 | { 66 | "cell_type": "markdown", 67 | "metadata": { 68 | "kernel": "SoS" 69 | }, 70 | "source": [ 71 | "is equivalent to" 72 | ] 73 | }, 74 | { 75 | "cell_type": "code", 76 | "execution_count": 3, 77 | "metadata": { 78 | "kernel": "SoS" 79 | }, 80 | "outputs": [ 81 | { 82 | "name": "stdout", 83 | "output_type": "stream", 84 | "text": [ 85 | "null device \n", 86 | " 1 \n" 87 | ] 88 | } 89 | ], 90 | "source": [ 91 | "R: expand=True, workdir='result'\n", 92 | " pdf('{res_file}')\n", 93 | " plot(0, 0)\n", 94 | " dev.off() " 95 | ] 96 | }, 97 | { 98 | "cell_type": "markdown", 99 | "metadata": { 100 | "kernel": "SoS" 101 | }, 102 | "source": [ 103 | "Or with different sigil" 104 | ] 105 | }, 106 | { 107 | "cell_type": "code", 108 | "execution_count": 4, 109 | "metadata": { 110 | "kernel": "SoS" 111 | }, 112 | "outputs": [ 113 | { 114 | "name": "stdout", 115 | "output_type": "stream", 116 | "text": [ 117 | "null device \n", 118 | " 1 \n" 119 | ] 120 | } 121 | ], 122 | "source": [ 123 | "R: expand='${ }', workdir='result'\n", 124 | " pdf('${res_file}')\n", 125 | " plot(0, 0)\n", 126 | " dev.off() " 127 | ] 128 | }, 129 | { 130 | "cell_type": "code", 131 | "execution_count": 5, 132 | "metadata": { 133 | "kernel": "SoS" 134 | }, 135 | "outputs": [], 136 | "source": [ 137 | "[RNASeq_20 (QC)]\n", 138 | "\n", 139 | "parameter: fastq_files = list\n", 140 | "\n", 141 | "input: fastq_files, group_by=1\n", 142 | "depends: executable('fastqc')\n", 143 | "output: f'{_input:bn}_fastqc_html'\n", 144 | "\n", 145 | "print(f'Processing {_input}')\n", 146 | "\n", 147 | "task: walltime='30m'\n", 148 | "\n", 149 | "sh: expand=True\n", 150 | " fastqc {_input}" 151 | ] 152 | }, 153 | { 154 | "cell_type": "markdown", 155 | "metadata": { 156 | "kernel": "SoS" 157 | }, 158 | "source": [ 159 | "### Interactive data analysis" 160 | ] 161 | }, 162 | { 163 | "cell_type": "markdown", 164 | "metadata": { 165 | "kernel": "SoS" 166 | }, 167 | "source": [ 168 | "Interactive data analysis can be performed in cells with different kernels as follows. Because SoS is an extension to Python 3, you can use arbitrary Python statements in SoS cells." 169 | ] 170 | }, 171 | { 172 | "cell_type": "code", 173 | "execution_count": 6, 174 | "metadata": { 175 | "kernel": "SoS" 176 | }, 177 | "outputs": [], 178 | "source": [ 179 | "excel_file = 'data/DEG.xlsx'\n", 180 | "csv_file = 'DEG.csv'\n", 181 | "figure_file = 'output.pdf'" 182 | ] 183 | }, 184 | { 185 | "cell_type": "code", 186 | "execution_count": 7, 187 | "metadata": { 188 | "kernel": "Bash" 189 | }, 190 | "outputs": [], 191 | "source": [ 192 | "%expand\n", 193 | "xlsx2csv {excel_file} > {csv_file}" 194 | ] 195 | }, 196 | { 197 | "cell_type": "code", 198 | "execution_count": 8, 199 | "metadata": { 200 | "kernel": "R" 201 | }, 202 | "outputs": [ 203 | { 204 | "data": { 205 | "text/html": [ 206 | "pdf: 2" 207 | ], 208 | "text/latex": [ 209 | "\\textbf{pdf:} 2" 210 | ], 211 | "text/markdown": [ 212 | "**pdf:** 2" 213 | ], 214 | "text/plain": [ 215 | "pdf \n", 216 | " 2 " 217 | ] 218 | }, 219 | "metadata": {}, 220 | "output_type": "display_data" 221 | } 222 | ], 223 | "source": [ 224 | "%expand\n", 225 | "data <- read.csv('{csv_file}')\n", 226 | "pdf('{figure_file}')\n", 227 | "plot(data$log2FoldChange, data$stat)\n", 228 | "dev.off()" 229 | ] 230 | }, 231 | { 232 | "cell_type": "markdown", 233 | "metadata": { 234 | "kernel": "R" 235 | }, 236 | "source": [ 237 | "### Convert to SoS actions" 238 | ] 239 | }, 240 | { 241 | "cell_type": "code", 242 | "execution_count": 1, 243 | "metadata": { 244 | "kernel": "SoS" 245 | }, 246 | "outputs": [], 247 | "source": [ 248 | "excel_file = 'data/DEG.xlsx'\n", 249 | "csv_file = 'DEG.csv'\n", 250 | "figure_file = 'output.pdf'" 251 | ] 252 | }, 253 | { 254 | "cell_type": "code", 255 | "execution_count": 5, 256 | "metadata": { 257 | "kernel": "SoS" 258 | }, 259 | "outputs": [], 260 | "source": [ 261 | "sh: expand=True\n", 262 | " xlsx2csv {excel_file} > {csv_file}" 263 | ] 264 | }, 265 | { 266 | "cell_type": "code", 267 | "execution_count": 6, 268 | "metadata": { 269 | "kernel": "SoS" 270 | }, 271 | "outputs": [ 272 | { 273 | "name": "stdout", 274 | "output_type": "stream", 275 | "text": [ 276 | "null device \n", 277 | " 1 \n" 278 | ] 279 | } 280 | ], 281 | "source": [ 282 | "R: expand=True\n", 283 | " data <- read.csv('{csv_file}')\n", 284 | " pdf('{figure_file}')\n", 285 | " plot(data$log2FoldChange, data$stat)\n", 286 | " dev.off()" 287 | ] 288 | }, 289 | { 290 | "cell_type": "markdown", 291 | "metadata": { 292 | "kernel": "R" 293 | }, 294 | "source": [ 295 | "### Conversion to a SoS Workflow" 296 | ] 297 | }, 298 | { 299 | "cell_type": "markdown", 300 | "metadata": { 301 | "kernel": "R" 302 | }, 303 | "source": [ 304 | "SoS workflows within a SoS Notebook are defined by sections marked by section headers (`[name: option]`). A `[global]` section should be used for definitions that will be used by all steps.\n", 305 | "\n", 306 | "You also need to convert scripts to SoS actions so that they can be executed as **complete** scripts. Remember also to change the cell type from subkernel to SoS." 307 | ] 308 | }, 309 | { 310 | "cell_type": "code", 311 | "execution_count": 7, 312 | "metadata": { 313 | "kernel": "SoS" 314 | }, 315 | "outputs": [], 316 | "source": [ 317 | "[global]\n", 318 | "excel_file = 'data/DEG.xlsx'\n", 319 | "csv_file = 'DEG.csv'\n", 320 | "figure_file = 'output.pdf'" 321 | ] 322 | }, 323 | { 324 | "cell_type": "code", 325 | "execution_count": 8, 326 | "metadata": { 327 | "kernel": "SoS" 328 | }, 329 | "outputs": [], 330 | "source": [ 331 | "[plot_1 (convert)]\n", 332 | "sh: expand=True\n", 333 | " xlsx2csv {excel_file} > {csv_file}" 334 | ] 335 | }, 336 | { 337 | "cell_type": "code", 338 | "execution_count": 9, 339 | "metadata": { 340 | "kernel": "SoS" 341 | }, 342 | "outputs": [], 343 | "source": [ 344 | "[plot_2 (plot)]\n", 345 | "R: expand=True\n", 346 | " data <- read.csv('{csv_file}')\n", 347 | " pdf('{figure_file}')\n", 348 | " plot(data$log2FoldChange, data$stat)\n", 349 | " dev.off()" 350 | ] 351 | }, 352 | { 353 | "cell_type": "code", 354 | "execution_count": 10, 355 | "metadata": { 356 | "kernel": "SoS" 357 | }, 358 | "outputs": [ 359 | { 360 | "name": "stdout", 361 | "output_type": "stream", 362 | "text": [ 363 | "null device \n", 364 | " 1 \n" 365 | ] 366 | }, 367 | { 368 | "data": { 369 | "text/html": [ 370 | "
INFO: Workflow plot (ID=e9a443b49c71e268) is executed successfully with 2 completed steps.
" 371 | ] 372 | }, 373 | "metadata": {}, 374 | "output_type": "display_data" 375 | } 376 | ], 377 | "source": [ 378 | "%sosrun plot" 379 | ] 380 | }, 381 | { 382 | "cell_type": "code", 383 | "execution_count": 16, 384 | "metadata": { 385 | "kernel": "SoS" 386 | }, 387 | "outputs": [ 388 | { 389 | "data": { 390 | "text/html": [ 391 | "" 426 | ], 427 | "text/plain": [ 428 | "#!/usr/bin/env sos-runner\n", 429 | "#fileformat=SOS1.0\n", 430 | "\n", 431 | "[RNASeq_20 (QC)]\n", 432 | "\n", 433 | "parameter: fastq_files = list\n", 434 | "\n", 435 | "input: fastq_files, group_by=1\n", 436 | "depends: executable('fastqc')\n", 437 | "output: f'{_input:bn}_fastqc_html'\n", 438 | "\n", 439 | "print(f'Processing {_input}')\n", 440 | "\n", 441 | "task: walltime='30m'\n", 442 | "\n", 443 | "sh: expand=True\n", 444 | " fastqc {_input}\n", 445 | "\n", 446 | "[global]\n", 447 | "excel_file = 'data/DEG.xlsx'\n", 448 | "csv_file = 'DEG.csv'\n", 449 | "figure_file = 'output.pdf'\n", 450 | "\n", 451 | "[plot_1 (convert)]\n", 452 | "sh: expand=True\n", 453 | " xlsx2csv {excel_file} > {csv_file}\n", 454 | "\n", 455 | "[plot_2 (plot)]\n", 456 | "R: expand=True\n", 457 | " data <- read.csv('{csv_file}')\n", 458 | " pdf('{figure_file}')\n", 459 | " plot(data$log2FoldChange, data$stat)\n", 460 | " dev.off()\n", 461 | "\n" 462 | ] 463 | }, 464 | "metadata": {}, 465 | "output_type": "display_data" 466 | } 467 | ], 468 | "source": [ 469 | "%preview --workflow" 470 | ] 471 | } 472 | ], 473 | "metadata": { 474 | "kernelspec": { 475 | "display_name": "SoS", 476 | "language": "sos", 477 | "name": "sos" 478 | }, 479 | "language_info": { 480 | "codemirror_mode": "sos", 481 | "file_extension": ".sos", 482 | "mimetype": "text/x-sos", 483 | "name": "sos", 484 | "nbconvert_exporter": "sos_notebook.converter.SoS_Exporter", 485 | "pygments_lexer": "sos" 486 | }, 487 | "sos": { 488 | "default_kernel": "SoS", 489 | "kernels": [ 490 | [ 491 | "Bash", 492 | "bash", 493 | "Bash", 494 | "#E6EEFF" 495 | ], 496 | [ 497 | "R", 498 | "ir", 499 | "R", 500 | "#DCDCDA" 501 | ], 502 | [ 503 | "SoS", 504 | "sos", 505 | "", 506 | "" 507 | ] 508 | ], 509 | "panel": { 510 | "displayed": false, 511 | "height": 0, 512 | "style": "side" 513 | }, 514 | "version": "0.16.11" 515 | } 516 | }, 517 | "nbformat": 4, 518 | "nbformat_minor": 2 519 | } 520 | -------------------------------------------------------------------------------- /6_Task.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": { 6 | "kernel": "SoS" 7 | }, 8 | "source": [ 9 | "## External tasks" 10 | ] 11 | }, 12 | { 13 | "cell_type": "markdown", 14 | "metadata": { 15 | "kernel": "SoS" 16 | }, 17 | "source": [ 18 | "The following workflow has a single step that generates a number of files with the number specified by parameter `num`." 19 | ] 20 | }, 21 | { 22 | "cell_type": "markdown", 23 | "metadata": { 24 | "kernel": "SoS" 25 | }, 26 | "source": [ 27 | "The following cell will not be executed directly (with `Ctrl-Enter` or `Shift-Enter`) because it is a formal SoS cell. It has to be executed by magic `%run` or `%sosrun`." 28 | ] 29 | }, 30 | { 31 | "cell_type": "code", 32 | "execution_count": 1, 33 | "metadata": { 34 | "kernel": "SoS" 35 | }, 36 | "outputs": [], 37 | "source": [ 38 | "[no_task]\n", 39 | "parameter: num = 2\n", 40 | "\n", 41 | "input: for_each = {'i': range(num)}\n", 42 | "output: f'test_{i}.txt'\n", 43 | "\n", 44 | "sh: expand=True\n", 45 | " sleep {3*i}\n", 46 | " echo test_{i} > test_{i}.txt\n", 47 | " echo \"Test_{i}.txt generated\"" 48 | ] 49 | }, 50 | { 51 | "cell_type": "code", 52 | "execution_count": 2, 53 | "metadata": { 54 | "kernel": "SoS" 55 | }, 56 | "outputs": [ 57 | { 58 | "name": "stdout", 59 | "output_type": "stream", 60 | "text": [ 61 | "Test_0.txt generated\n", 62 | "Test_1.txt generated\n" 63 | ] 64 | } 65 | ], 66 | "source": [ 67 | "%sosrun no_task" 68 | ] 69 | }, 70 | { 71 | "cell_type": "markdown", 72 | "metadata": { 73 | "kernel": "SoS" 74 | }, 75 | "source": [ 76 | "When we rerun the workflow with option `--num 3` to generate one more file, the first two are ignored because they have already been generated." 77 | ] 78 | }, 79 | { 80 | "cell_type": "code", 81 | "execution_count": 3, 82 | "metadata": { 83 | "kernel": "SoS" 84 | }, 85 | "outputs": [ 86 | { 87 | "name": "stdout", 88 | "output_type": "stream", 89 | "text": [ 90 | "Test_2.txt generated\n" 91 | ] 92 | } 93 | ], 94 | "source": [ 95 | "%sosrun no_task --num 3" 96 | ] 97 | }, 98 | { 99 | "cell_type": "markdown", 100 | "metadata": { 101 | "kernel": "SoS" 102 | }, 103 | "source": [ 104 | "Keyword `task` separates the reset of the step process as external tasks:" 105 | ] 106 | }, 107 | { 108 | "cell_type": "code", 109 | "execution_count": 4, 110 | "metadata": { 111 | "kernel": "SoS" 112 | }, 113 | "outputs": [], 114 | "source": [ 115 | "[task]\n", 116 | "parameter: num = 2\n", 117 | "\n", 118 | "input: for_each = {'i': range(num)}\n", 119 | "output: f'test_{i}.txt'\n", 120 | "\n", 121 | "task:\n", 122 | "sh: expand=True\n", 123 | " sleep {5*i}\n", 124 | " echo test_{i} > test_{i}.txt\n", 125 | " echo \"Test_{i}.txt generated\"" 126 | ] 127 | }, 128 | { 129 | "cell_type": "code", 130 | "execution_count": 8, 131 | "metadata": { 132 | "kernel": "SoS", 133 | "scrolled": true 134 | }, 135 | "outputs": [ 136 | { 137 | "data": { 138 | "text/html": [ 139 | "
2 tasks completed: 0d99,99f5
" 140 | ] 141 | }, 142 | "metadata": {}, 143 | "output_type": "display_data" 144 | }, 145 | { 146 | "name": "stdout", 147 | "output_type": "stream", 148 | "text": [ 149 | "\n" 150 | ] 151 | } 152 | ], 153 | "source": [ 154 | "%sosrun task -s force" 155 | ] 156 | }, 157 | { 158 | "cell_type": "markdown", 159 | "metadata": { 160 | "kernel": "SoS" 161 | }, 162 | "source": [ 163 | "## Concurrent execution and external tasks" 164 | ] 165 | }, 166 | { 167 | "cell_type": "code", 168 | "execution_count": 6, 169 | "metadata": { 170 | "kernel": "SoS" 171 | }, 172 | "outputs": [ 173 | { 174 | "name": "stdout", 175 | "output_type": "stream", 176 | "text": [ 177 | "Counting lines of data/S20_R1.fastq\n", 178 | " 2000 data/S20_R1.fastq\n", 179 | "Counting lines of data/S20_R2.fastq\n", 180 | " 2000 data/S20_R2.fastq\n" 181 | ] 182 | } 183 | ], 184 | "source": [ 185 | "input: 'data/*.fastq', group_by=1, concurrent=True\n", 186 | "\n", 187 | "sh: expand=True\n", 188 | " echo \"Counting lines of {_input}\"\n", 189 | " sleep {5 * _index}\n", 190 | " wc -l {_input}" 191 | ] 192 | }, 193 | { 194 | "cell_type": "code", 195 | "execution_count": 9, 196 | "metadata": { 197 | "kernel": "SoS" 198 | }, 199 | "outputs": [ 200 | { 201 | "data": { 202 | "text/html": [ 203 | "
2 tasks completed: 7dfc,e082
" 204 | ] 205 | }, 206 | "metadata": {}, 207 | "output_type": "display_data" 208 | }, 209 | { 210 | "name": "stdout", 211 | "output_type": "stream", 212 | "text": [ 213 | "\n" 214 | ] 215 | } 216 | ], 217 | "source": [ 218 | "input: 'data/*.fastq', group_by=1\n", 219 | "\n", 220 | "task:\n", 221 | "sh: expand=True\n", 222 | " echo \"Counting lines of {_input}\"\n", 223 | " sleep {5 * _index}\n", 224 | " wc -l {_input}" 225 | ] 226 | } 227 | ], 228 | "metadata": { 229 | "kernelspec": { 230 | "display_name": "SoS", 231 | "language": "sos", 232 | "name": "sos" 233 | }, 234 | "language_info": { 235 | "codemirror_mode": "sos", 236 | "file_extension": ".sos", 237 | "mimetype": "text/x-sos", 238 | "name": "sos", 239 | "nbconvert_exporter": "sos_notebook.converter.SoS_Exporter", 240 | "pygments_lexer": "sos" 241 | }, 242 | "sos": { 243 | "default_kernel": "SoS", 244 | "kernels": [ 245 | [ 246 | "SoS", 247 | "sos", 248 | "", 249 | "" 250 | ] 251 | ], 252 | "panel": { 253 | "displayed": true, 254 | "height": 0, 255 | "style": "side" 256 | }, 257 | "version": "0.9.16.7" 258 | } 259 | }, 260 | "nbformat": 4, 261 | "nbformat_minor": 2 262 | } 263 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | # Copyright (c) Bo Peng and the University of Texas MD Anderson Cancer Center 2 | # Distributed under the terms of the 3-clause BSD License. 3 | 4 | FROM vatlab/sos-notebook 5 | 6 | MAINTAINER Bo Peng 7 | 8 | USER root 9 | COPY . ${HOME} 10 | RUN chown -R ${NB_UID} ${HOME} 11 | USER ${NB_USER} 12 | 13 | # Specify the default command to run 14 | CMD ["jupyter", "lab", "--ip", "0.0.0.0"] 15 | 16 | 17 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Stephen Eglen 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # SoS: Using multiple kernels in a notebook 2 | 3 | [Script of Scripts](https://vatlab.github.io/sos-docs) is a polyglot 4 | notebook and a workflow engine. Ignoring the workflow engine part, SoS 5 | Notebook provides a SoS Kernel that acts as a super kernel to all Jupyter 6 | kernels so that you can use multiple Jupyter kernels in a single Jupyter 7 | notebook. Moreover, it provides a number of magics, most importantly `%get` 8 | to exchange variables between live kernels of supported languages. 9 | 10 | ![sos-notebook](sos-notebook.png) 11 | 12 | ## Use SoS with binder 13 | 14 | Although it is almost trivial to install SoS, setting up multiple kernels 15 | in a single binder environment is not very easy at this point. This repository 16 | contains multiple branches that demonstrates how to do it for the languages 17 | you are interested in. For more details, please refer to the [SoS 18 | Documentation](https://vatlab.github.io/sos-docs) on how to set up 19 | different kernels for SoS. 20 | 21 | ### The master branch 22 | 23 | [![Binder](http://mybinder.org/badge.svg)](https://mybinder.org/v2/gh/binder-examples/jupyter-sos/master) 24 | 25 | The master branch uses a `Dockerfile` to set up most kernels that SoS 26 | supports. The docker file is derived from [mdabioinfo/sos-notebook](https://hub.docker.com/r/mdabioinfo/sos-notebook/tags/), which is in turn derived from [Jupyter Notebook Data Science 27 | Stack](https://github.com/jupyter/docker-stacks/tree/master/datascience-notebook) and contains the following kernels: 28 | 29 | * Python 2 kernel for Python 2.7 30 | * Python 3 kernel for Python 3.6 31 | * [Bash kernel](https://github.com/takluyver/bash_kernel) for using bash commands 32 | * [iJavaScript](https://github.com/n-riesco/ijavascript) for node.js 33 | * [iJulia](https://github.com/JuliaLang/IJulia.jl) for Julia 34 | * [ir](https://github.com/IRkernel/IRkernel) kernel for R 35 | * [markdown](https://github.com/vatlab/markdown-kernel) kernel that allows the expansion of SoS (Python) expressions in markdown contents. 36 | * [Octave Kernel](https://github.com/Calysto/octave_kernel) for octave 37 | * [SPARQL kernel](https://github.com/paulovn/sparql-kernel) for Sparql, included to demonstrate how SoS works with 38 | any Jupyter kernel (not in a language that SoS understands) 39 | 40 | SoS also supports other languages such as Ruby, MATLAB, and SAS but they 41 | are not included since this image is already very big. 42 | 43 | This branch includes mostly examples for a talk on SoS during JupyterCon2018. You can watch the talk on Youtube 44 | using [this link](https://www.youtube.com/watch?v=U75eKosFbp8) if you are intested in learning SoS. 45 | 46 | 47 | ### The Python-Julia branch 48 | 49 | [![Binder](http://mybinder.org/badge.svg)](https://mybinder.org/v2/gh/binder-examples/jupyter-sos/python-julia) 50 | 51 | This branch is much more lightweight as it contains only Python 3, Julia, 52 | and SoS kernels. It specifies the environment using 53 | 54 | * `environment.yml`: an anaconda python environment, also installs SoS and SoS Notebook 55 | * `REQURE`: a Julia environment with recommended packages 56 | * `postBuild`: Post build command to install the SoS Kernel. 57 | 58 | This branch contains a notebook `python-and-julia.ipynb` which demonstrates 59 | how to use Python3 and Julia in a single Jupyter notebook. 60 | 61 | ### The Python-R branch 62 | 63 | [![Binder](http://mybinder.org/badge.svg)](https://mybinder.org/v2/gh/binder-examples/jupyter-sos/python-r) 64 | 65 | This branch contains only Python 3, R, and SoS kernels. It specifies the environment using 66 | 67 | * `environment.yml`: an anaconda python environment, also installs SoS and SoS Notebook 68 | * `runtime.txt`: specify version of R as [MRAN](https://mran.microsoft.com/) snapshots 69 | * `install.R`: additional packages to install 70 | * `postBuild`: Post build command to install the SoS Kernel. 71 | 72 | This branch contains a notebook `python-and-r.ipynb` which demonstrates 73 | how to use Python3 and R in a single Jupyter notebook. 74 | 75 | -------------------------------------------------------------------------------- /REQUIRE: -------------------------------------------------------------------------------- 1 | PyPlot 2 | Feather 3 | DataFrames 4 | NamedArrays 5 | -------------------------------------------------------------------------------- /sos-notebook.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/binder-examples/jupyter-sos/b1e5b13c99944371fc0257808d50c15b92e459da/sos-notebook.png --------------------------------------------------------------------------------