├── .gitignore ├── LICENSE ├── README.md ├── package-lock.json ├── package.json ├── public ├── favicon.ico ├── index.html ├── logo192.png ├── logo512.png ├── manifest.json └── robots.txt ├── rollup.config.js ├── src ├── App.js ├── index.js ├── lib │ ├── BlockOutput.tsx │ ├── BlockSource.tsx │ ├── Editor.tsx │ ├── JupyterViewer.scss │ ├── JupyterViewer.tsx │ ├── hljsStyles.ts │ └── types.ts └── nb_test.json └── tsconfig.json /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # production 12 | /build 13 | 14 | # misc 15 | .DS_Store 16 | .env.local 17 | .env.development.local 18 | .env.test.local 19 | .env.production.local 20 | 21 | npm-debug.log* 22 | yarn-debug.log* 23 | yarn-error.log* 24 | 25 | # distribution 26 | /dist 27 | 28 | # idea 29 | /.idea 30 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Litao Qiao 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 | # react-jupyter-notebook 2 | 3 | A simple React component that renders .ipynb files just like how they are rendered by JupyterLab. 4 | 5 | Demo: https://joeyonng.github.io/react-jupyter-notebook/ 6 | 7 | ### Why 8 | I created this component because I want to embed a pure frontend jupyter notebooks (ipynb files) viewer into my personal 9 | website, which is built using React. 10 | 11 | This project was inspired by [React-Jupyter-Viewer](https://github.com/ShivBhosale/React-Jupyter-Viewer). I still 12 | reinvented the wheel since I prefer the original looking of JupyterLab. 13 | 14 | ### Install 15 | ```bash 16 | npm install --save react-jupyter-notebook 17 | ``` 18 | 19 | ### Features 20 | * [X] Nearly identical looking to original JupyterLab interface. 21 | * [X] Can render codes, images, outputs, markdown(equations) and HTML in the notebook. 22 | * [X] Enable resizing the height of the scrolled output. 23 | * [X] Can change the alignment of the media outputs. 24 | * [X] Customisable code block styling. 25 | 26 | ### Usage 27 | ```javascript 28 | import React from 'react'; 29 | import ReactDOM from 'react-dom'; 30 | import JupyterViewer from "react-jupyter-notebook"; 31 | import nb_test from "./nb_test.json"; // You need to read the .ipynb file into a JSON Object. 32 | 33 | ReactDOM.render( 34 | 35 | 36 | , 37 | document.getElementById('root') 38 | ); 39 | ``` 40 | 41 | ### Props 42 | | Prop name | Type | Description | (*default*) Values | 43 | |-----------------|---------|-----------------------------------------------------------------|------------------------------------| 44 | | rawIpynb | Object | The JSON object converted from the .ipynb file. | | 45 | | language | String | The programming language used in the notebook. | *"python"*, [others][language] | 46 | | showLineNumbers | Boolean | Show or hide the line numbers. | *true*, false | 47 | | mediaAlign | String | How to align medias (images, HTML). | *"center"*, "left", "right" | 48 | | displaySource | String | How source cells are displayed. | *"auto"*, "hide", "show" | 49 | | displayOutput | String | How output cells are displayed. | *"auto"*, "hide", "show", "scroll" | 50 | | codeBlockStyles | Object | Customize code cells styles. Use JupyterLab theme if undefined. | *undefined*, {...} | 51 | 52 | ### Customising code block styles (codeBlockStyles prop) 53 | I use [React Syntax Highlighter](https://github.com/react-syntax-highlighter/react-syntax-highlighter) for the syntax 54 | highlighting. One little problem with React Syntax Highlighter is that the whole line number container cannot be 55 | separately styled. The line number part in the original JupyterLab theme has a different background color with the codes 56 | part, so they need to be separately styled. My solution is to use two `` components: one displays line 57 | numbers, and the other displays codes themselves. 58 | 59 | You can use codeBlockStyles prop to pass the props to the SyntaxHighlighter to customize your own code block styles. 60 | Please read the docs of React Syntax Highlighter if you want to use this prop. 61 | 62 | | Property Name | Type | Description | Which `` | 63 | |--------------------------|--------|----------------------------------------------------------|------------------------------| 64 | | hljsStyle | String | Name of the highlight.js style object. See [here][hljs]. | Both line number and code. | 65 | | lineNumberStyle | Object | Style object for every line numbers object. | Line number. | 66 | | lineNumberContainerStyle | Object | Style object for the container of line numbers. | Line number. | 67 | | codeContainerStyle | Object | Style object for the container of the codes. | Code. | 68 | 69 | [language]: https://github.com/react-syntax-highlighter/react-syntax-highlighter/blob/master/AVAILABLE_LANGUAGES_HLJS.MD 70 | [hljs]: https://github.com/react-syntax-highlighter/react-syntax-highlighter/blob/master/AVAILABLE_STYLES_HLJS.MD 71 | 72 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-jupyter-notebook", 3 | "version": "0.3.2", 4 | "homepage": "https://Joeyonng.github.io/react-jupyter-notebook", 5 | "license": "MIT", 6 | "private": false, 7 | "description": "A simple React component that renders .ipynb files just like how they are rendered by Jupyter Lab", 8 | "repository": { 9 | "type": "git", 10 | "url": "https://github.com/Joeyonng/react-jupyter-notebook" 11 | }, 12 | "keywords": [ 13 | "React", 14 | "Jupyter", 15 | "Notebook", 16 | "ipynb" 17 | ], 18 | "author": { 19 | "name": "Litao Qiao", 20 | "email": "checkpppp@gmail.com" 21 | }, 22 | "files": [ 23 | "dist" 24 | ], 25 | "main": "dist/index.js", 26 | "module": "dist/index.mjs", 27 | "typeings": "dist/index.d.ts", 28 | "dependencies": { 29 | "@codemirror/gutter": "^0.19.9", 30 | "@codemirror/lang-javascript": "^0.19.7", 31 | "@codemirror/view": "^0.19.47", 32 | "ansi-to-react": "^6.1.4", 33 | "katex": "^0.13.2", 34 | "react": "^17.0.1", 35 | "react-dom": "^17.0.1", 36 | "react-markdown": "^6.0.2", 37 | "react-syntax-highlighter": "^15.4.3", 38 | "rehype-katex": "^5.0.0", 39 | "remark-gfm": "^1.0.0", 40 | "remark-math": "^4.0.0" 41 | }, 42 | "devDependencies": { 43 | "@types/node": "^17.0.23", 44 | "@types/react": "^17.0.42", 45 | "@types/react-dom": "^17.0.14", 46 | "@types/react-syntax-highlighter": "^13.5.2", 47 | "gh-pages": "^3.2.0", 48 | "node-sass": "^6.0.1", 49 | "react-scripts": "5.0.0", 50 | "rimraf": "^3.0.2", 51 | "rollup": "^2.70.1", 52 | "rollup-plugin-dts": "^4.2.0", 53 | "rollup-plugin-postcss": "^4.0.2", 54 | "rollup-plugin-typescript2": "^0.31.2", 55 | "typescript": "^4.6.2" 56 | }, 57 | "scripts": { 58 | "start": "react-scripts start", 59 | "build": "react-scripts build", 60 | "test": "react-scripts test", 61 | "eject": "react-scripts eject" 62 | }, 63 | "eslintConfig": { 64 | "extends": [ 65 | "react-app", 66 | "react-app/jest" 67 | ] 68 | }, 69 | "browserslist": { 70 | "production": [ 71 | ">0.2%", 72 | "not dead", 73 | "not op_mini all" 74 | ], 75 | "development": [ 76 | "last 1 chrome version", 77 | "last 1 firefox version", 78 | "last 1 safari version" 79 | ] 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Joeyonng/react-jupyter-notebook/deddebcce78180818ba0d8479edf09f86f42f9ed/public/favicon.ico -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 12 | 13 | 17 | 18 | 27 | react jupyter notebook 28 | 29 | 30 | 31 |
32 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Joeyonng/react-jupyter-notebook/deddebcce78180818ba0d8479edf09f86f42f9ed/public/logo192.png -------------------------------------------------------------------------------- /public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Joeyonng/react-jupyter-notebook/deddebcce78180818ba0d8479edf09f86f42f9ed/public/logo512.png -------------------------------------------------------------------------------- /public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | }, 10 | { 11 | "src": "logo192.png", 12 | "type": "image/png", 13 | "sizes": "192x192" 14 | }, 15 | { 16 | "src": "logo512.png", 17 | "type": "image/png", 18 | "sizes": "512x512" 19 | } 20 | ], 21 | "start_url": ".", 22 | "display": "standalone", 23 | "theme_color": "#000000", 24 | "background_color": "#ffffff" 25 | } 26 | -------------------------------------------------------------------------------- /public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /rollup.config.js: -------------------------------------------------------------------------------- 1 | import externals from "rollup-plugin-node-externals"; 2 | import typescript from 'rollup-plugin-typescript2'; 3 | import postcss from "rollup-plugin-postcss"; 4 | import dts from "rollup-plugin-dts"; 5 | 6 | import packageJson from "./package.json"; 7 | 8 | export default [ 9 | { 10 | input: "src/lib/JupyterViewer.tsx", 11 | output: [ 12 | { 13 | file: packageJson.main, 14 | format: "cjs", 15 | sourcemap: true, 16 | }, 17 | ], 18 | plugins: [ 19 | externals(), 20 | typescript({ 21 | tsconfig: "tsconfig.json", 22 | tsconfigOverride: {compilerOptions: {declaration: true}}, 23 | }), 24 | postcss(), 25 | ], 26 | }, 27 | { 28 | input: "dist/JupyterViewer.d.ts", 29 | output: [{file: packageJson.typeings, format: "es"}], 30 | external: [/\.scss$/], 31 | plugins: [dts()], 32 | }, 33 | ]; -------------------------------------------------------------------------------- /src/App.js: -------------------------------------------------------------------------------- 1 | import React, {useState} from 'react'; 2 | import nb_test from "./nb_test.json" 3 | 4 | import JupyterViewer from "./lib/JupyterViewer"; 5 | import hljsStyles from "./lib/hljsStyles"; 6 | 7 | function App() { 8 | const [state, setState] = useState({ 9 | rawIpynb: nb_test, 10 | mediaAlign: "left", 11 | displaySource: "auto", 12 | displayOutput: "auto", 13 | showLineNumbers: true, 14 | codeBlockStyles: undefined, 15 | }) 16 | 17 | return ( 18 | 19 |
25 | { 29 | if (e.target.files[0]) { 30 | const reader = new FileReader(); 31 | reader.readAsText(e.target.files[0], "UTF-8"); 32 | reader.onload = (e) => { 33 | setState({...state, rawIpynb: JSON.parse(e.target.result)}) 34 | }; 35 | reader.onerror = (e) => { 36 | console.log('reader error!', e) 37 | }; 38 | } 39 | }} 40 | /> 41 |
42 | 43 | 53 |
54 |
55 | 56 | 66 |
67 |
68 | 69 | 80 |
81 |
82 | 83 | 92 |
93 |
94 | 95 | 111 |
112 |
113 | 114 | {!state.rawIpynb ? null : 115 | 123 | } 124 |
125 | ) 126 | } 127 | 128 | export default App; -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import App from "./App"; 4 | 5 | ReactDOM.render( 6 | 7 | 8 | , 9 | document.getElementById('root') 10 | ); -------------------------------------------------------------------------------- /src/lib/BlockOutput.tsx: -------------------------------------------------------------------------------- 1 | import React, {useCallback, useState} from "react"; 2 | import Ansi from "ansi-to-react"; 3 | 4 | import {BlockOutputPropsType} from "./types"; 5 | 6 | function BlockOutput(props:BlockOutputPropsType) { 7 | const metadata = props.cell['metadata']; 8 | const outputs = props.cell['outputs'] 9 | 10 | const [state, setState] = useState({ 11 | highlighted: false, 12 | prevDisplay: 1, 13 | display: 1, 14 | contentHeight: 0, 15 | }) 16 | const contentRef = useCallback((node) => { 17 | if (node) { 18 | setState(state => ({...state, contentHeight: node.offsetHeight})); 19 | } 20 | }, []) 21 | 22 | if (props.display !== state.prevDisplay) { 23 | let newDisplay = props.display; 24 | if (newDisplay === -1) { 25 | if (metadata['collapsed'] || (metadata['jupyter'] !== undefined && metadata['jupyter']['outputs_hidden'])) { 26 | newDisplay = 0; 27 | } 28 | else if (metadata['scrolled']) { 29 | newDisplay = 2; 30 | } 31 | } 32 | 33 | setState({...state, prevDisplay: props.display, display: newDisplay}); 34 | } 35 | 36 | return ( 37 |
40 |
{ 43 | setState({...state, display: (state.display + 1) % 3}) 44 | }} 45 | /> 46 | {state.display === 0 ?
: 47 |
56 |
57 | {!outputs ? null : outputs.map((output, index) => { 58 | let executionCount; 59 | let htmlContent; 60 | if ('output_type' in output) { 61 | let output_type = output['output_type']; 62 | switch (output_type) { 63 | // Stdout and stderr 64 | case 'stream': 65 | htmlContent = ( 66 |
 67 |                         {!output['text'] ? '' : output['text'].join('')}
 68 |                       
69 | ) 70 | 71 | break; 72 | // Output with execution_count 73 | // @ts-expect-error 74 | case 'execute_result': 75 | executionCount = output['execution_count'] 76 | 77 | // Output without execution_count 78 | case 'display_data': 79 | const output_data = output['data']; 80 | if (output_data) { 81 | if ('image/png' in output_data) { 82 | let output_metadata = output['metadata']; 83 | let size = output_metadata && output_metadata['image/png']; 84 | htmlContent = ( 85 |
91 | 97 |
98 | ) 99 | } 100 | else if ('text/html' in output_data) { 101 | htmlContent = ( 102 |
109 | ) 110 | } 111 | else if ('text/plain' in output_data) { 112 | htmlContent = ( 113 |
{output_data['text/plain'].join('')}
114 | ) 115 | } 116 | } 117 | 118 | break; 119 | // Exceptions 120 | case 'error': 121 | htmlContent = ( 122 |
123 |                         
124 |                           {!output.traceback ? undefined : output.traceback.join('\n')}
125 |                         
126 |                       
127 | ) 128 | 129 | break; 130 | default: 131 | console.log('Unexpected output_type: ', output_type); 132 | } 133 | } 134 | 135 | return ( 136 |
140 |
{executionCount ? `[${executionCount}]: ` : null}
141 | {htmlContent} 142 |
143 | ); 144 | })} 145 |
146 |
147 | } 148 |
149 | ) 150 | } 151 | 152 | export default BlockOutput; -------------------------------------------------------------------------------- /src/lib/BlockSource.tsx: -------------------------------------------------------------------------------- 1 | import React, {useState} from "react"; 2 | import SyntaxHighlighter from "react-syntax-highlighter"; 3 | import ReactMarkdown from "react-markdown"; 4 | import RemarkGFM from "remark-gfm"; 5 | import RemarkMath from "remark-math"; 6 | import RehypeKatex from "rehype-katex"; 7 | import 'katex/dist/katex.min.css'; 8 | 9 | import hljsStyles from "./hljsStyles"; 10 | import {BlockSourcePropsType, codeBlockStylesType} from "./types"; 11 | 12 | function BlockSource(props:BlockSourcePropsType) { 13 | const metadata = props.cell['metadata']; 14 | const source = props.cell['source']; 15 | const type = props.cell['cell_type']; 16 | 17 | const [state, setState] = useState({ 18 | prevDisplay: 1, 19 | display: 1, 20 | contentHeight: 0, 21 | }) 22 | 23 | if (props.display !== state.prevDisplay) { 24 | let newDisplay = props.display; 25 | if (newDisplay === -1) { 26 | if (metadata['jupyter'] !== undefined && metadata['jupyter']['source_hidden']) { 27 | newDisplay = 0; 28 | } 29 | } 30 | 31 | setState({...state, prevDisplay: props.display, display: newDisplay}); 32 | } 33 | 34 | let htmlContent; 35 | let executionCount; 36 | if (type === 'code') { 37 | executionCount = props.cell['execution_count']; 38 | 39 | // SyntaxHighlighter originally doesn't separate the line numbers and the codes. 40 | // The first SyntaxHighlighter is used to show line numbers only and the second is to show codes only. 41 | const {hljsStyle, lineNumberStyle, lineNumberContainerStyle, codeContainerStyle} = props.codeBlockStyles 42 | || {} as codeBlockStylesType; 43 | 44 | htmlContent = ( 45 |
46 | {!props.showLineNumbers ? null : 47 | 73 | {!source ? null : source.map((item, index) => index === 0 ? ' ' : '\n').join('')} 74 | 75 | } 76 | 77 |
78 | 96 | {!source ? null : source.join('')} 97 | 98 |
99 |
100 | ) 101 | } 102 | else if (type === 'markdown') { 103 | // '$$' has to be in a separate new line to be rendered as a block math equation. 104 | const re = /\n?\s*\$\$\s*\n?/g; 105 | const newSource = !source ? '' : source.join('').replaceAll(re, "\n$$$\n") 106 | 107 | htmlContent = ( 108 |
109 | 113 | {newSource} 114 | 115 |
116 | ) 117 | } 118 | else { 119 | htmlContent = ( 120 |
{`Cell Type ${type} not supported...`}
121 | ) 122 | } 123 | 124 | return ( 125 |
126 |
{ 129 | setState({...state, display: (state.display + 1) % 2}) 130 | }} 131 | /> 132 | 133 | {state.display === 0 ?
: 134 |
135 |
{executionCount ? `[${executionCount}]: ` : null}
136 | {htmlContent} 137 |
138 | } 139 |
140 | ) 141 | } 142 | 143 | export default BlockSource; -------------------------------------------------------------------------------- /src/lib/Editor.tsx: -------------------------------------------------------------------------------- 1 | import React, {useEffect, useRef, useState} from "react"; 2 | import {EditorState, StateEffect} from '@codemirror/state'; 3 | import {EditorView, keymap, ViewUpdate, placeholder} from '@codemirror/view'; 4 | import {lineNumbers} from "@codemirror/gutter"; 5 | import {javascript} from "@codemirror/lang-javascript" 6 | 7 | declare interface EditorPropsType { 8 | editable: boolean, 9 | onChange: (change: string) => void, 10 | } 11 | 12 | function Editor(props: EditorPropsType) { 13 | const { 14 | editable=true, 15 | onChange=(value) => console.log(value), 16 | } = props; 17 | 18 | const [state, setState] = useState<{[key:string]: any}>({}); 19 | 20 | const extensions = [ 21 | javascript(), 22 | lineNumbers(), 23 | // onChange listener 24 | EditorView.updateListener.of((viewUpdate: ViewUpdate) => { 25 | if (viewUpdate.docChanged && typeof onChange === 'function') { 26 | const doc = viewUpdate.state.doc; 27 | const value = doc.toString(); 28 | onChange(value); 29 | } 30 | }), 31 | // Jupyter theme 32 | EditorView.theme( 33 | { 34 | '&.cm-editor': { 35 | border: "1px solid rgb(224, 224, 224)", 36 | backgroundColor: "rgb(245, 245, 245)", 37 | }, 38 | '&.cm-editor.cm-focused': { 39 | outline: "1px solid #1976d2", 40 | }, 41 | '.cm-gutters': { 42 | minWidth: "37px", 43 | display: "initial", 44 | backgroundColor: "rgb(238, 238, 238)" 45 | } 46 | }, 47 | {dark: false}, 48 | ), 49 | // Editable 50 | EditorView.editable.of(editable), 51 | ]; 52 | 53 | const codeMirrorRef = useRef(null); 54 | useEffect(() => { 55 | if (codeMirrorRef.current && !state.view) { 56 | const view = new EditorView({ 57 | state: EditorState.create({ 58 | extensions: extensions, 59 | doc: "TEST", 60 | }), 61 | parent: codeMirrorRef.current, 62 | }) 63 | setState((state) => ({...state, view})) 64 | } 65 | }, [codeMirrorRef.current]) 66 | 67 | return ( 68 |
69 | ) 70 | } 71 | 72 | export default Editor; -------------------------------------------------------------------------------- /src/lib/JupyterViewer.scss: -------------------------------------------------------------------------------- 1 | // Add a vertical bar in front of the markdown blockquotes (lines starting with >). 2 | blockquote { 3 | border-left: 0.5em #eee solid; 4 | } 5 | 6 | .jupyter-viewer { 7 | width: 100%; 8 | height: 100%; 9 | } 10 | 11 | .block { 12 | padding: 5px 5px 5px 5px; 13 | box-sizing: border-box; 14 | overflow: hidden; 15 | 16 | .block-hidden { 17 | width: 100%; 18 | min-height: 20px; 19 | } 20 | 21 | .block-source { 22 | width: 100%; 23 | box-sizing: border-box; 24 | 25 | display: flex; 26 | flex-direction: row; 27 | } 28 | 29 | .block-output { 30 | width: 100%; 31 | margin: 5px 0 0 0; 32 | box-sizing: border-box; 33 | 34 | display: flex; 35 | flex-direction: row; 36 | 37 | .block-output-content { 38 | width: 100%; 39 | overflow-y: auto; 40 | } 41 | } 42 | 43 | .block-light { 44 | width: 8px; 45 | margin: 0 5px 0 0; 46 | 47 | border-radius: 2px; 48 | background-color: rgba(66, 165, 245, 0); 49 | 50 | &:hover { 51 | background-color: rgba(66, 165, 245, 0.75); 52 | } 53 | } 54 | 55 | .block-light-selected { 56 | width: 8px; 57 | margin: 0 5px 0 0; 58 | 59 | border-radius: 2px; 60 | background-color: rgba(66, 165, 245, 1); 61 | 62 | &:hover { 63 | background-color: darken(rgba(66, 165, 245, 1), 20%); 64 | } 65 | } 66 | 67 | .cell-row { 68 | width: 100%; 69 | display: flex; 70 | flex-direction: row; 71 | 72 | .cell-header { 73 | width: 64px; 74 | margin: 0 0 0 0; 75 | padding: 5px 0 0 5px; 76 | box-sizing: border-box; 77 | 78 | text-align: right; 79 | 80 | &.source { 81 | color: #307fc1; 82 | } 83 | 84 | &.output { 85 | color: #bf5b3d; 86 | } 87 | } 88 | 89 | .cell-content { 90 | width: 100%; 91 | margin: 0 0 0 0; 92 | box-sizing: border-box; 93 | flex: 1; 94 | 95 | &.source-code { 96 | display: flex; 97 | flex-direction: row; 98 | 99 | .source-code-main { 100 | flex: 1; 101 | } 102 | } 103 | 104 | &.source-markdown { 105 | padding: 0 20px 0 5px; 106 | box-sizing: border-box; 107 | 108 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; 109 | font-size: 14px; 110 | } 111 | 112 | &.output-std { 113 | padding: 5px 0 0 5px; 114 | box-sizing: border-box; 115 | } 116 | 117 | &.output-err { 118 | padding: 5px 0 0 5px; 119 | box-sizing: border-box; 120 | background-color: #FFDDDD; 121 | } 122 | 123 | &.output-display { 124 | display: flex; 125 | flex-direction: row; 126 | } 127 | } 128 | } 129 | } 130 | -------------------------------------------------------------------------------- /src/lib/JupyterViewer.tsx: -------------------------------------------------------------------------------- 1 | import React, {useState} from 'react'; 2 | 3 | import BlockSource from "./BlockSource"; 4 | import BlockOutput from "./BlockOutput"; 5 | 6 | import './JupyterViewer.scss'; 7 | import {JupyterViewerPropsType} from "./types"; 8 | 9 | // -1: auto, 0: hide, 1: show, 2: scroll 10 | const DISPLAYS = ['hide', 'show', 'scroll']; 11 | 12 | function JupyterViewer(props:JupyterViewerPropsType) { 13 | const { 14 | rawIpynb, 15 | language='python', 16 | showLineNumbers=true, 17 | mediaAlign='center', 18 | displaySource='auto', 19 | displayOutput='auto', 20 | codeBlockStyles=undefined, 21 | } = props; 22 | 23 | const [state, setState] = useState({ 24 | clickCellIndex: -1, 25 | }) 26 | 27 | return ( 28 |
29 | {rawIpynb['cells'].map((cell, index) => { 30 | return ( 31 |
{ 35 | setState({...state, clickCellIndex: index}) 36 | }} 37 | > 38 | {!('cell_type' in cell) ? null : 39 | 47 | } 48 | {!('outputs' in cell) ? null : 49 | 55 | } 56 |
57 | ) 58 | })} 59 |
60 | ) 61 | } 62 | 63 | export default JupyterViewer; -------------------------------------------------------------------------------- /src/lib/hljsStyles.ts: -------------------------------------------------------------------------------- 1 | import * as hljs from 'react-syntax-highlighter/dist/esm/styles/hljs'; 2 | 3 | const hljsStyles: {[key: string]: {}} = { 4 | 'a11yDark': hljs.a11yDark, 5 | 'a11yLight': hljs.a11yLight, 6 | 'agate': hljs.agate, 7 | 'anOldHope': hljs.anOldHope, 8 | 'androidstudio': hljs.androidstudio, 9 | 'arduinoLight': hljs.arduinoLight, 10 | 'arta': hljs.arta, 11 | 'ascetic': hljs.ascetic, 12 | 'atelierCaveDark': hljs.atelierCaveDark, 13 | 'atelierCaveLight': hljs.atelierCaveLight, 14 | 'atelierDuneDark': hljs.atelierDuneDark, 15 | 'atelierDuneLight': hljs.atelierDuneLight, 16 | 'atelierEstuaryDark': hljs.atelierEstuaryDark, 17 | 'atelierEstuaryLight': hljs.atelierEstuaryLight, 18 | 'atelierForestDark': hljs.atelierForestDark, 19 | 'atelierForestLight': hljs.atelierForestLight, 20 | 'atelierHeathDark': hljs.atelierHeathDark, 21 | 'atelierHeathLight': hljs.atelierHeathLight, 22 | 'atelierLakesideDark': hljs.atelierLakesideDark, 23 | 'atelierLakesideLight': hljs.atelierLakesideLight, 24 | 'atelierPlateauDark': hljs.atelierPlateauDark, 25 | 'atelierPlateauLight': hljs.atelierPlateauLight, 26 | 'atelierSavannaDark': hljs.atelierSavannaDark, 27 | 'atelierSavannaLight': hljs.atelierSavannaLight, 28 | 'atelierSeasideDark': hljs.atelierSeasideDark, 29 | 'atelierSeasideLight': hljs.atelierSeasideLight, 30 | 'atelierSulphurpoolDark': hljs.atelierSulphurpoolDark, 31 | 'atelierSulphurpoolLight': hljs.atelierSulphurpoolLight, 32 | 'atomOneDarkReasonable': hljs.atomOneDarkReasonable, 33 | 'atomOneDark': hljs.atomOneDark, 34 | 'atomOneLight': hljs.atomOneLight, 35 | 'brownPaper': hljs.brownPaper, 36 | 'codepenEmbed': hljs.codepenEmbed, 37 | 'colorBrewer': hljs.colorBrewer, 38 | 'darcula': hljs.darcula, 39 | 'dark': hljs.dark, 40 | 'defaultStyle': hljs.defaultStyle, 41 | 'docco': hljs.docco, 42 | 'dracula': hljs.dracula, 43 | 'far': hljs.far, 44 | 'foundation': hljs.foundation, 45 | 'githubGist': hljs.githubGist, 46 | 'github': hljs.github, 47 | 'gml': hljs.gml, 48 | 'googlecode': hljs.googlecode, 49 | 'gradientDark': hljs.gradientDark, 50 | 'grayscale': hljs.grayscale, 51 | 'gruvboxDark': hljs.gruvboxDark, 52 | 'gruvboxLight': hljs.gruvboxLight, 53 | 'hopscotch': hljs.hopscotch, 54 | 'hybrid': hljs.hybrid, 55 | 'idea': hljs.idea, 56 | 'irBlack': hljs.irBlack, 57 | 'isblEditorDark': hljs.isblEditorDark, 58 | 'isblEditorLight': hljs.isblEditorLight, 59 | 'kimbieDark': hljs.kimbieDark, 60 | 'kimbieLight': hljs.kimbieLight, 61 | 'lightfair': hljs.lightfair, 62 | 'lioshi': hljs.lioshi, 63 | 'magula': hljs.magula, 64 | 'monoBlue': hljs.monoBlue, 65 | 'monokaiSublime': hljs.monokaiSublime, 66 | 'monokai': hljs.monokai, 67 | 'nightOwl': hljs.nightOwl, 68 | 'nnfxDark': hljs.nnfxDark, 69 | 'nnfx': hljs.nnfx, 70 | 'nord': hljs.nord, 71 | 'obsidian': hljs.obsidian, 72 | 'ocean': hljs.ocean, 73 | 'paraisoDark': hljs.paraisoDark, 74 | 'paraisoLight': hljs.paraisoLight, 75 | 'pojoaque': hljs.pojoaque, 76 | 'purebasic': hljs.purebasic, 77 | 'qtcreatorDark': hljs.qtcreatorDark, 78 | 'qtcreatorLight': hljs.qtcreatorLight, 79 | 'railscasts': hljs.railscasts, 80 | 'rainbow': hljs.rainbow, 81 | 'routeros': hljs.routeros, 82 | 'schoolBook': hljs.schoolBook, 83 | 'shadesOfPurple': hljs.shadesOfPurple, 84 | 'solarizedDark': hljs.solarizedDark, 85 | 'solarizedLight': hljs.solarizedLight, 86 | 'srcery': hljs.srcery, 87 | 'sunburst': hljs.sunburst, 88 | 'tomorrowNightBlue': hljs.tomorrowNightBlue, 89 | 'tomorrowNightBright': hljs.tomorrowNightBright, 90 | 'tomorrowNightEighties': hljs.tomorrowNightEighties, 91 | 'tomorrowNight': hljs.tomorrowNight, 92 | 'tomorrow': hljs.tomorrow, 93 | 'vs': hljs.vs, 94 | 'vs2015': hljs.vs2015, 95 | 'xcode': hljs.xcode, 96 | 'xt256': hljs.xt256, 97 | 'zenburn': hljs.zenburn, 98 | } 99 | 100 | export default hljsStyles; -------------------------------------------------------------------------------- /src/lib/types.ts: -------------------------------------------------------------------------------- 1 | import "" 2 | export interface codeBlockStylesType { 3 | hljsStyle: string, 4 | lineNumberStyle?: {}, 5 | lineNumberContainerStyle?: {}, 6 | codeContainerStyle?: {}, 7 | } 8 | 9 | export interface cellOutputType { 10 | name?: string, 11 | data?: {[key: string]: any}, 12 | metadata?: {[key: string]: any}, 13 | output_type?: string, 14 | text?: string[], 15 | execution_count?: number, 16 | traceback?: string[], 17 | } 18 | 19 | export interface cellType { 20 | cell_type?: string, 21 | execution_count?: number, 22 | metadata: { 23 | scrolled?: boolean, 24 | collapsed?: boolean, 25 | jupyter?: { 26 | source_hidden?: boolean, 27 | outputs_hidden?: boolean, 28 | }, 29 | }, 30 | outputs?: cellOutputType[], 31 | source?: string[], 32 | } 33 | 34 | export interface BlockSourcePropsType { 35 | cell: cellType, 36 | language: string, 37 | display: number, 38 | highlighted: boolean, 39 | showLineNumbers: boolean, 40 | codeBlockStyles?: codeBlockStylesType, 41 | } 42 | 43 | export interface BlockOutputPropsType { 44 | cell: cellType, 45 | display: number, 46 | highlighted: boolean, 47 | mediaAlign: string, 48 | codeBlockStyles?: codeBlockStylesType, 49 | } 50 | 51 | export interface JupyterViewerPropsType { 52 | rawIpynb: { 53 | cells: cellType[], 54 | }, 55 | language?: string, 56 | showLineNumbers?: boolean, 57 | mediaAlign?: 'left' | 'center' | 'right', 58 | displaySource?: 'auto' | 'hide' | 'show', 59 | displayOutput?: 'auto' | 'hide' | 'show' | 'scroll', 60 | codeBlockStyles?: codeBlockStylesType, 61 | } -------------------------------------------------------------------------------- /src/nb_test.json: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "https://www.semanticscholar.org/paper/Fast-Effective-Rule-Induction-Cohen/6665e03447f989c9bdb3432d93e89b516b9d18a7\n", 8 | "#### IREP\n", 9 | "Given a training set $\\mathcal{D}$ with binary labels and all possible features $\\mathcal{F}$ in $\\mathcal{F}$,\n", 10 | "1. Randomly choose 2/3 from $\\mathcal{D}$ as the growing set $\\mathcal{G}$ and the rest 1/3 becomes the pruning set $\\mathcal{P}$. \n", 11 | "2. Initialize an empty rule set $\\mathcal{R}$.\n", 12 | "3. While there are still positive instances in $\\mathcal{G}$:\n", 13 | " 1. Initialize a empty rule $R$.\n", 14 | " 2. Until all instances that satisfy $R$ are positive (accuracy of $R$ is 1) or there is no feature to add: \n", 15 | " 1. For every feature $f \\in \\mathcal{F}$ not in $R$ and every possible value $v$ of $f$:\n", 16 | " 1. Create a temp rule $R_{t}$ by copying current $R$. \n", 17 | " 2. Add $f=v$ to $R_{t}$.\n", 18 | " 3. Calculate FOIL's information gain of $R_{t}$: $\\mathrm{Foil}(R, R_{t})$ based on $\\mathcal{G}$.\n", 19 | " 2. Get the $R_{t}^{max}$ with the max value of $\\mathrm{Foil}(R_{t})$.\n", 20 | " 3. $R=R_{t}^{max}$\n", 21 | "\n", 22 | "**[FOIL's information gain]**: it gives how much information entropy is reduced from $R_{old}$ to $R_{new}$.\n", 23 | "$$ \\mathrm{Foil}(R_{old}, R_{new}) = P(R_{old}) (\\log_{2}(\\frac{P(R_{old})}{P(R_{old}) + N(R_{old})}) - \\log_{2}(\\frac{P(R_{new})}{P(R_{new}) + N(R_{new})})) $$\n", 24 | "where $P(R)$ is the number of positive instances covered by $R$ and $N(R)$ is the number of negative instances covered by $R$.\n", 25 | "\n", 26 | "**[IREP Rule value]**: \n", 27 | "$$ \\mathrm{Value}(R) = \\frac{P(R) + (N - N(R))}{P + N} $$\n", 28 | "where $P$ is the total number of positive instances, $N$ is the total number of negative instances, $P(R)$ is the number of positive instances covered by $R$ and $N(R)$ is the number of negative instances covered by $R$." 29 | ] 30 | }, 31 | { 32 | "cell_type": "markdown", 33 | "metadata": {}, 34 | "source": [ 35 | "Cell with an image output, a stdout and a stderr (error)." 36 | ] 37 | }, 38 | { 39 | "cell_type": "code", 40 | "execution_count": 1, 41 | "metadata": { 42 | "tags": [] 43 | }, 44 | "outputs": [ 45 | { 46 | "data": { 47 | "image/png": "iVBORw0KGgoAAAANSUhEUgAAAjcAAAGdCAYAAADuR1K7AAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjQuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8rg+JYAAAACXBIWXMAAA9hAAAPYQGoP6dpAABJEUlEQVR4nO3dd3wUdeL/8demE0hCTQIkIEgJLQ1FggVUFBEVRFESf+Ld4XnnhSbKCeqp2IKnoDRBj1PuPEMX9BApIkWaCEkgCb0mAklo6X13fn/4Pe4iLQtJJrt5Px+PfTzc2ZnNO+Nm9818PjtjMQzDQERERMRJuJgdQERERKQqqdyIiIiIU1G5EREREaeiciMiIiJOReVGREREnIrKjYiIiDgVlRsRERFxKio3IiIi4lTczA5Q02w2GydPnsTHxweLxWJ2HBEREakEwzDIy8ujRYsWuLhc+dhMnSs3J0+eJDg42OwYIiIicg3S09MJCgq64jp1rtz4+PgAv+wcX19fk9OIiIhIZeTm5hIcHHzhc/xK6ly5+c9QlK+vr8qNiIiIg6nMlBJNKBYRERGnonIjIiIiTkXlRkRERJyKyo2IiIg4FZUbERERcSoqNyIiIuJUVG5ERETEqajciIiIiFNRuRERERGnUmvKzaRJk7BYLIwZM+aK6y1atIiQkBC8vLzo1q0bK1asqJmAIiIi4hBqRbn56aef+PjjjwkNDb3ielu2bCE6Oprhw4eTmJjIoEGDGDRoECkpKTWUVERERGo708tNfn4+TzzxBH/7299o1KjRFdedOnUq9913H+PGjaNTp068+eabREZGMmPGjBpKKyIiIrWd6eUmNjaWAQMG0Ldv36uuu3Xr1ovW69evH1u3br3sNiUlJeTm5la4iYiISNXLKy5j1LxEVqdmmJrD1KuCz58/n4SEBH766adKrZ+RkUFAQECFZQEBAWRkXH4nxsXFMXHixOvKKSIiIleWciKHEfEJHDtbyOZDZ7i9fTPqebiaksW0Izfp6emMHj2aL774Ai8vr2r7ORMmTCAnJ+fCLT09vdp+loiISF1jGAb/3HqMwR9t4djZQlr4efHJsJtMKzZg4pGbnTt3kpWVRWRk5IVlVquVjRs3MmPGDEpKSnB1rbhjAgMDyczMrLAsMzOTwMDAy/4cT09PPD09qza8iIiIkFNUxoQvd7Mi+ZcRlL6dAnh/SCgNvT1MzWVaubn77rtJTk6usOy3v/0tISEhvPjiixcVG4CoqCjWrl1b4evia9asISoqqrrjioiIyP/YlZ7NiHkJpJ8rwt3Vwov3hTD8tjZYLBazo5lXbnx8fOjatWuFZfXr16dJkyYXlg8bNoyWLVsSFxcHwOjRo+nduzeTJ09mwIABzJ8/nx07dvDJJ5/UeH4REZG6yDAMPt18jEnf7qXMahDUqB4zYiIJD25odrQLTJ1QfDVpaWm4uPx3WlCvXr2Ij4/nlVde4aWXXqJ9+/YsW7bsopIkIiIiVS+7sJQXFu3mu72/TBG5r0sg7z4ail89d5OTVWQxDMMwO0RNys3Nxc/Pj5ycHHx9fc2OIyIi4hB2Hj/PqHmJnMguwsPVhZcHdGJYVOsaG4ay5/O7Vh+5EREREXPZbAZ/++EI763aT7nNoHUTb2bGRNK1pZ/Z0S5L5UZEREQu6VxBKc8vTGLd/tMAPBDanLjB3fDxql3DUL+mciMiIiIX2X70HKPmJZKRW4yHmwuvP9iF6B7BteLbUFejciMiIiIX2GwGszYcZsqaA1htBm2b1mfmE5F0au4481RVbkRERASAM/klPLcgiR8OngHg4YiWvDWoK/U9HasuOFZaERERqRZbD59l9PxEsvJK8HJ34Y2HujLkpiCHGIb6NZUbERGROsxqM5j+/UGmrT2IzYD2/g2Y+UQkHQJ8zI52zVRuRERE6qis3GLGLEhiy+GzAAzpHsTEgV3w9nDseuDY6UVEROSa/HDwNM8tSOJMfineHq68NagrgyODzI5VJVRuRERE6pByq40PvzvIzPWHMAwICfRhRkwk7fwbmB2tyqjciIiI1BEZOcWMmpfI9mPnAIju0YrXHuyMl7urycmqlsqNiIhIHbBufxbPL9zFuYJS6nu4EvdIKA+FtTA7VrVQuREREXFiZVYb76/ez8cbjgDQpYUvM2IiadO0vsnJqo/KjYiIiJM6kV3EqHmJ7Dx+HoBhUa156f5OTjcM9WsqNyIiIk7ouz2ZPL9oFzlFZfh4uvHuo6Hc36252bFqhMqNiIiIEyktt/HXlfuYs+koAKFBfsyIjqRVE2+Tk9UclRsREREnkX6ukBHzEtmVng3A725tw/j+IXi4uZgbrIap3IiIiDiBlSmnGLd4N3nF5fh6ufH+kDDu7RJodixTqNyIiIg4sJJyK+98s5d/bD0OQESrhkyPjiCoUd0Zhvo1lRsREREHdexMASPmJZByIheAP9zRlhf6dcTdtW4NQ/2ayo2IiIgDWr77JOOXJJNfUk4jb3cmPxbGXSEBZseqFVRuREREHEhxmZU3lu8h/sc0AG6+oRHToiNo7lfP5GS1h8qNiIiIgzh8Op/YLxLYl5GHxQJ/6nMjz/XtgFsdH4b6NZUbERERB7As8QQvLU2msNRKk/oefPB4OHd0aGZ2rFpJ5UZERKQWKyq18vrXqSzYkQ5Az7aNmTo0ggBfL5OT1V4qNyIiIrXUwcw8YuMTOJCZj8UCo+5qz6i72+PqYjE7Wq2mciMiIlILLdqRzqtfpVJUZqWZjydTHw+nV7umZsdyCCo3IiIitUhBSTl/+SqFLxNOAHBbu6Z88Hg4zXw8TU7mOFRuREREaol9GbnEfpHA4dMFuFhg7D0d+FOfdrhoGMouKjciIiImMwyD+T+l8/rXqZSU2wjw9WTa0AhuadvE7GgOSeVGRETERHnFZby0NIV/7zoJQO8OzZjyWBhNGmgY6lqp3IiIiJgk5UQOI+ITOHa2EFcXC+P6deSZ29tqGOo6qdyIiIjUMMMw+Ne247y5fC+lVhst/LyYHhNB99aNzY7mFFRuREREalBucRnjl+xmRXIGAH07+fPeo2E0qu9hcjLnoXIjIiJSQ3b/nE1sfALp54pwc7Ewvn8Iw29rg8WiYaiqpHIjIiJSzQzD4LPNx4j7di9lVoOgRvWYERNJeHBDs6M5JZUbERGRapRdWMq4xbtZsycTgPu6BPLuo6H41XM3OZnzUrkRERGpJglp5xkZn8iJ7CI8XF14eUAnhkW11jBUNVO5ERERqWI2m8GcTUf468r9lNsMWjfxZkZ0JN2C/MyOVieo3IiIiFShcwWlvLBoF9/vywJgQGhzJg3uho+XhqFqisqNiIhIFfnp2DlGzUvkVE4xHm4uvPZgZ2J6tNIwVA1TuREREblONpvBrA2HmbLmAFabQdum9ZkRE0nnFr5mR6uTVG5ERESuw5n8Ep5bkMQPB88AMCi8BW893I0GnvqINYv2vIiIyDXaevgso+cnkpVXgpe7C2881JUhNwVpGMpkKjciIiJ2stoMZnx/iKlrD2AzoJ1/A2bGRNIx0MfsaAK4mPnDZ82aRWhoKL6+vvj6+hIVFcW333572fXnzp2LxWKpcPPy8qrBxCIiUtdl5RXz5N9/5IPvfik2Q7oH8fWIW1VsahFTj9wEBQUxadIk2rdvj2EY/OMf/2DgwIEkJibSpUuXS27j6+vL/v37L9zXoT8REakpmw6eYcyCRM7kl1LP3ZW3H+7K4Mggs2PJr5habh588MEK999++21mzZrFtm3bLltuLBYLgYGBNRFPREQEgHKrjalrDzJj3SEMA0ICfZgRE0k7/wZmR5NLqDVzbqxWK4sWLaKgoICoqKjLrpefn0/r1q2x2WxERkbyzjvvXLYIAZSUlFBSUnLhfm5ubpXmFhER55aRU8yo+YlsP3oOgOgewbz2YBe83F1NTiaXY3q5SU5OJioqiuLiYho0aMDSpUvp3LnzJdft2LEjn376KaGhoeTk5PD+++/Tq1cvUlNTCQq69GHBuLg4Jk6cWJ2/goiIOKn1+7MYu3AX5wpKqe/hyjuDuzEwvKXZseQqLIZhGGYGKC0tJS0tjZycHBYvXsycOXPYsGHDZQvO/yorK6NTp05ER0fz5ptvXnKdSx25CQ4OJicnB19fnVxJREQuVma1MXn1AWZvOAxA5+a+zHwikjZN65ucrO7Kzc3Fz8+vUp/fph+58fDwoF27dgB0796dn376ialTp/Lxxx9fdVt3d3ciIiI4dOjQZdfx9PTE09OzyvKKiIhzO5ldxMh5iew8fh6AJ3u25uUBnTQM5UBMLze/ZrPZKhxpuRKr1UpycjL3339/NacSEZG64Ls9mbyweBfZhWX4eLrx7qOh3N+tudmxxE6mlpsJEybQv39/WrVqRV5eHvHx8axfv55Vq1YBMGzYMFq2bElcXBwAb7zxBj179qRdu3ZkZ2fz3nvvcfz4cZ5++mkzfw0REXFwpeU2/rpyH3M2HQUgNMiPGdGRtGribXIyuRamlpusrCyGDRvGqVOn8PPzIzQ0lFWrVnHPPfcAkJaWhovLf88zeP78eX7/+9+TkZFBo0aN6N69O1u2bKnU/BwREZFLST9XyIh5iexKzwbgd7e24cX+HfF00zCUozJ9QnFNs2dCkoiIOLeVKRn8efEucovL8fVy4/0hYdzbRedSq40cakKxiIhITSsptxK3Yh9ztxwDIKJVQ6ZHRxDUSMNQzkDlRkRE6pTjZwsYEZ9I8okcAJ65oy3j+nXE3dXUyy1KFVK5ERGROmP57pOMX5JMfkk5jbzdmfxYGHeFBJgdS6qYyo2IiDi94jIrby7fwxc/pgFwU+tGTI+JoLlfPZOTSXVQuREREad25HQ+sfGJ7D31y7UF/9TnRsbe0wE3DUM5LZUbERFxWssST/DS0mQKS600qe/BlMfD6d2hmdmxpJqp3IiIiNMpKrXy+tepLNiRDkDPto2ZOjSCAF8vk5NJTVC5ERERp3IoK4/YLxLZn5mHxQIj72rP6Lvb4+piMTua1BCVGxERcRqLd/7MX5alUFRmpWkDT6YNDadXu6Zmx5IapnIjIiIOr6CknL98lcKXCScAuK1dUz54PJxmPp4mJxMzqNyIiIhD25eRS+wXCRw+XYCLBZ7r24E/3dlOw1B1mMqNiIg4JMMwWPBTOq99nUpJuY0AX0+mDo2gZ9smZkcTk6nciIiIw8kvKeelL5P5etdJAHp3aMaUx8Jo0kDDUKJyIyIiDib1ZA4j4hM5eqYAVxcLL9zbkT/c0RYXDUPJ/1G5ERERh2AYBv/6MY03l++htNxGCz8vpsdE0L11Y7OjSS2jciMiIrVebnEZE5Yk803yKQD6dvLnvUfDaFTfw+RkUhup3IiISK22++dsRsQnknauEDcXC+P7hzD8tjZYLBqGkktTuRERkVrJMAzmbjnGOyv2UmY1aNmwHjNiIoho1cjsaFLLqdyIiEitk1NYxrjFu1i9JxOAfl0C+OsjYfh5u5ucTByByo2IiNQqiWnnGRGfyInsIjxcXXjp/hCe6nWDhqGk0lRuRESkVrDZDP6+6SjvrtxHuc2gVWNvZsZE0i3Iz+xo4mBUbkRExHTnC0p5ftEuvt+XBcCA0ObEDe6Gr5eGocR+KjciImKqHcfOMXJeIqdyivFwc+HVBzrzxC2tNAwl10zlRkRETGGzGczeeJjJqw9gtRm0bVqfGTGRdG7ha3Y0cXAqNyIiUuPO5JcwduEuNh44DcCg8Ba89XA3GnjqY0mun15FIiJSo7YdOcuoeYlk5ZXg5e7CxIe68NhNwRqGkiqjciMiIjXCajOYue4QH353AJsB7fwbMDMmko6BPmZHEyejciMiItUuK6+Y5xYksfnQWQAe7R7EGwO74O2hjyGpenpViYhItdp86Ayj5ydxJr+Eeu6uvDWoK490DzI7ljgxlRsREakW5VYb09YeZPq6QxgGdAzwYeYTEbTz1zCUVC+VGxERqXKZucWMnJfI9qPnAIjuEcxrD3bBy93V5GRSF6jciIhIlVq/P4uxC3dxrqCU+h6uvDO4GwPDW5odS+oQlRsREakS5VYbk9ccYNb6wwB0bu7LjJgI2jZrYHIyqWtUbkRE5LqdzC5i1LxEdhw/D8CTPVvz8oBOGoYSU6jciIjIdVm7N5PnF+0iu7AMH083Jj0SyoDQ5mbHkjpM5UZERK5JabmN91bt428/HAWgW0s/ZsRE0LpJfZOTSV2nciMiInZLP1fIyHmJJKVnA/DbW29gfP8QPN00DCXmU7kRERG7rErNYNyiXeQWl+Pr5cZ7Q8Lo1yXQ7FgiF6jciIhIpZSUW4lbsY+5W44BEB7ckOnREQQ39jY3mMivqNyIiMhVHT9bwIj4RJJP5ADwzB1tGdevI+6uLiYnE7mYyo2IiFzRN7tPMX7JbvJKymno7c6Ux8K4KyTA7Fgil6VyIyIil1RcZuWtb/bwr21pANzUuhHToiNo0bCeyclErkzlRkRELnLkdD6x8YnsPZULwJ/63MjYezrgpmEocQAqNyIiUsFXSSd46ctkCkqtNKnvwZTHw+ndoZnZsUQqTeVGREQAKCq1MvHfqcz/KR2AW9o0Zlp0BAG+XiYnE7GPqccXZ82aRWhoKL6+vvj6+hIVFcW33357xW0WLVpESEgIXl5edOvWjRUrVtRQWhER53UoK49BMzcz/6d0LBYYdXd7vnj6FhUbcUimlpugoCAmTZrEzp072bFjB3fddRcDBw4kNTX1kutv2bKF6Ohohg8fTmJiIoMGDWLQoEGkpKTUcHIREeexeOfPPDh9M/sz82jawJN/Db9F82vEoVkMwzDMDvG/GjduzHvvvcfw4cMveuzxxx+noKCA5cuXX1jWs2dPwsPDmT17dqWePzc3Fz8/P3JycvD19a2y3CIijqawtJy/LEtlScLPANzargkfPB6Ov4+O1kjtY8/nd62Zc2O1Wlm0aBEFBQVERUVdcp2tW7cyduzYCsv69evHsmXLLvu8JSUllJSUXLifm5tbJXlFRBzZ/ow8YuMTOJSVj4sFnuvbgT/d2Q5XF4vZ0USum+nlJjk5maioKIqLi2nQoAFLly6lc+fOl1w3IyODgICKJ44KCAggIyPjss8fFxfHxIkTqzSziIijMgyDBT+l89rXqZSU2wjw9WTq0Ah6tm1idjSRKmP6gGrHjh1JSkrixx9/5Nlnn+Wpp55iz549Vfb8EyZMICcn58ItPT29yp5bRMSR5JeUM2ZBEuO/TKak3EbvDs34ZtTtKjbidEw/cuPh4UG7du0A6N69Oz/99BNTp07l448/vmjdwMBAMjMzKyzLzMwkMPDyV6P19PTE09OzakOLiDiY1JM5jIxP5MiZAlxdLLxwb0f+cEdbXDQMJU7I9CM3v2az2SrMkflfUVFRrF27tsKyNWvWXHaOjohIXWcYBp9vO87DH23hyJkCmvt5seCZnjzb50YVG3Faph65mTBhAv3796dVq1bk5eURHx/P+vXrWbVqFQDDhg2jZcuWxMXFATB69Gh69+7N5MmTGTBgAPPnz2fHjh188sknZv4aIiK1Um5xGRO+TOab3acAuDvEn/eHhNGovofJyUSql6nlJisri2HDhnHq1Cn8/PwIDQ1l1apV3HPPPQCkpaXh4vLfg0u9evUiPj6eV155hZdeeon27duzbNkyunbtatavICJSKyX/nENsfAJp5wpxc7Ewvn8Iw29rg8WiozXi/Ow+z016ejoWi4WgoCAAtm/fTnx8PJ07d+aZZ56plpBVSee5ERFnZhgG/9hyjHdW7KPUaqNlw3rMiIkgolUjs6OJXBd7Pr/tnnMTExPDunXrgF++mn3PPfewfft2Xn75Zd54441rSywiItctp7CMP/5rJ6//ew+lVhv3dg5gxajbVWykzrG73KSkpNCjRw8AFi5cSNeuXdmyZQtffPEFc+fOrep8IiJSCYlp5xkw/QdWpWbi7mrhtQc78/GT3fHzdjc7mkiNs3vOTVlZ2YWvVn/33Xc89NBDAISEhHDq1KmqTSciIldkGAZzfjjKuyv3UW4zaNXYmxkxEYQGNTQ7mohp7D5y06VLF2bPns0PP/zAmjVruO+++wA4efIkTZroRFAiIjXlfEEpT/9jB2+v2Eu5zWBAt+YsH3Wbio3UeXYfuXn33Xd5+OGHee+993jqqacICwsD4Ouvv74wXCUiItVrx7FzjJqXyMmcYjzcXHj1gc48cUsrfRtKBDvLjWEYtG3blrS0NMrLy2nU6L+T1J555hm8vb2rPKCIiPyXzWYwe+NhJq8+gNVm0KZpfWbERNClhZ/Z0URqDbvLTbt27UhNTaV9+/YVHrvhhhuqMpeIiPzK2fwSxi7cxYYDpwEYGN6Ctx/uRgNP06+kI1Kr2PUX4eLiQvv27Tl79uxF5UZERKrPj0fOMmp+Ipm5JXi6ufDGwC48dlOwhqFELsHuCcWTJk1i3LhxpKSkVEceERH5H1abwfS1B4n+2zYyc0u4sVl9vh5xG4/frPk1Ipdj9xmKGzVqRGFhIeXl5Xh4eFCvXr0Kj587d65KA1Y1naFYRBzF6bwSxixIZPOhswA8EhnEm4O64O2hYSipe+z5/Lb7L+TDDz+81lwiIlJJmw+dYfT8JM7kl1DP3ZU3B3Xl0e5BZscScQh2l5unnnqqOnKIiAi/DENNXXuQ6d8fxDCgY4APM2IiaB/gY3Y0EYdh95wbgMOHD/PKK68QHR1NVlYWAN9++y2pqalVGk5EpC7JzC3miTnbmLb2l2Iz9OZglsXeqmIjYie7y82GDRvo1q0bP/74I19++SX5+fkA7Nq1i9dee63KA4qI1AUbDpzm/qk/sO3IOep7uDJ1aDiTHgmlnoer2dFEHI7d5Wb8+PG89dZbrFmzBg8PjwvL77rrLrZt21al4UREnF251ca7K/fx1KfbOVtQSqfmvvx75G0MDG9pdjQRh2X3nJvk5GTi4+MvWu7v78+ZM2eqJJSISF1wMruIUfMS2XH8PAD/r2crXhnQGS93Ha0RuR52l5uGDRty6tQp2rRpU2F5YmIiLVvqXxoiIpXx/b5Mxi7cRXZhGT6ebsQ90o0HQluYHUvEKdg9LDV06FBefPFFMjIysFgs2Gw2Nm/ezAsvvMCwYcOqI6OIiNMos9p4Z8Vefjd3B9mFZXRr6cfyUbep2IhUIbuP3LzzzjvExsYSHByM1Wqlc+fOWK1WYmJieOWVV6ojo4iIU/j5fCEj4hNJSs8G4De9bmDC/SF4umkYSqQq2X2G4v9IS0sjJSWF/Px8IiIiHOZaUzpDsYiYYVVqBuMW7SK3uBxfLzf++mgY93UNNDuWiMOo1jMU/0erVq0IDg4G0PVNREQuo7TcRty3e/ls8zEAwoIbMiM6guDG3uYGE3Fi13QSv7///e907doVLy8vvLy86Nq1K3PmzKnqbCIiDi3tbCGPzt5yodj8/vY2LPpDlIqNSDWz+8jNq6++ypQpUxg5ciRRUVEAbN26leeee460tDTeeOONKg8pIuJoViSf4sXFu8krKaehtzvvPxpG384BZscSqRPsnnPTrFkzpk2bRnR0dIXl8+bNY+TIkbX+XDeacyMi1am4zMrb3+zl823HAejeuhHToyNo0bCeyclEHFu1zrkpKyvjpptuumh59+7dKS8vt/fpREScxtEzBcR+kcCeU7kAPNvnRsbe0wF312uaASAi18juv7gnn3ySWbNmXbT8k08+4YknnqiSUCIijuarpBM8MO0H9pzKpXF9D+b+9mZevC9ExUbEBJU6cjN27NgL/22xWJgzZw6rV6+mZ8+eAPz444+kpaXpJH4iUucUl1mZ+O9U5m1PB6BHm8ZMGxpBoJ+XyclE6q5KlZvExMQK97t37w7A4cOHAWjatClNmzYlNTW1iuOJiNReh7Lyif0igf2ZeVgsMPLOdoy6uz1uOlojYqpKlZt169ZVdw4REYeyZOfPvLIshaIyK00bePLh4+Hc1r6p2bFEhOs4iZ+ISF1UWFrOq1+lsnjnzwD0urEJHw4Nx99Hw1AitYXd5aa4uJjp06ezbt06srKysNlsFR5PSEiosnAiIrXJgcw8Yr9I4GBWPi4WGNO3A7F3tsPVRWdpF6lN7C43w4cPZ/Xq1Tz66KP06NFDl14QEadnGAYLd6Tz2tepFJfZ8PfxZOrQCKJubGJ2NBG5BLvLzfLly1mxYgW33nprdeQREalV8kvKeWVpMsuSTgJwe/umfPB4OE0beJqcTEQux+5y07JlS3x8fKoji4hIrbLnZC4j4hM4cqYAVxcLz9/bgT/ecSMuGoYSqdXs/r7i5MmTefHFFzl+/Hh15BERMZ1hGPxr23EGfbSZI2cKaO7nxfxnevKnPu1UbEQcgN1Hbm666SaKi4tp27Yt3t7euLu7V3j83LlzVRZORKSm5RWXMf7LZL7ZfQqAu0L8eX9IGI3re5icTEQqy+5yEx0dzYkTJ3jnnXcICAjQhGIRcRrJP+cwYl4Cx88W4uZi4cX7Qhh+WxsdrRFxMHaXmy1btrB161bCwsKqI4+ISI0zDIN/bDnGOyv2UWq10bJhPabHRBDZqpHZ0UTkGthdbkJCQigqKqqOLCIiNS6nqIwXF+9mZWoGAPd2DuC9R8Pw83a/ypYiUlvZXW4mTZrE888/z9tvv023bt0umnPj6+tbZeFERKpTUno2I+IT+Pl8Ee6uFl66vxO/6XWDhttFHJzFMAzDng1cXH75gtWv//gNw8BisWC1WqsuXTXIzc3Fz8+PnJwcFTGROsowDP6+6SiTvt1Huc2gVWNvZsREEBrU0OxoInIZ9nx+233kRhfRFBFHll1YyguLdvHd3iwA7u8WyKRHQvH10jCUiLOwu9z07t27OnKIiFS7ncfPMTI+kZM5xXi4ufCXBzrz/25ppWEoESdjd7nZuHHjFR+/4447rjmMiEh1sNkMPt54hPdX78dqM2jTtD4zYiLo0sLP7GgiUg3sLjd9+vS5aNn//qunts+5EZG65Wx+Cc8v2sX6/acBeCisBe8M7kYDT7vf/kTEQdh9+YXz589XuGVlZbFy5UpuvvlmVq9ebddzxcXFcfPNN+Pj44O/vz+DBg1i//79V9xm7ty5WCyWCjcvLy97fw0RqQN+PHKW+6f9wPr9p/F0cyFucDemDg1XsRFxcnb/hfv5XXwY95577sHDw4OxY8eyc+fOSj/Xhg0biI2N5eabb6a8vJyXXnqJe++9lz179lC/fv3Lbufr61uhBGm8XET+l9Vm8NG6Q3zw3QFsBtzYrD4zn4gkJFDfkBSpC6rsny8BAQFXPeryaytXrqxwf+7cufj7+7Nz584rzt2xWCwEBgZeU04RcW6n80p4bkESmw6dAWBwZEveHNiV+jpaI1Jn2P3Xvnv37gr3DcPg1KlTTJo0ifDw8OsKk5OTA0Djxo2vuF5+fj6tW7fGZrMRGRnJO++8Q5cuXS65bklJCSUlJRfu5+bmXldGEam9thw6w+gFSZzOK6GeuytvDOzCkJuCzY4lIjXsmk7iZ7FY+PVmPXv25NNPPyUkJOSagthsNh566CGys7PZtGnTZdfbunUrBw8eJDQ0lJycHN5//302btxIamoqQUFBF63/+uuvM3HixIuW6yR+Is7DajOYuvYg078/iGFAh4AGzIyJpH2Aj9nRRKSK2HMSP7vLzfHjxyvcd3FxoVmzZtc9qffZZ5/l22+/ZdOmTZcsKZdTVlZGp06diI6O5s0337zo8UsduQkODla5EXESmbnFjJ6fyLYj5wB4/KZgXn+oC/U8XE1OJiJVqVrPUNy6detrDnY5I0aMYPny5WzcuNGuYgPg7u5OREQEhw4duuTjnp6eeHp6VkVMEallNh44zXMLkjhbUIq3hyvvPNyNQREtzY4lIia7phl2a9euZe3atWRlZWGz2So89umnn1b6eQzDYOTIkSxdupT169fTpk0bu7NYrVaSk5O5//777d5WRBxTudXGlDUH+Gj9YQA6NfdlZkwEbZs1MDmZiNQGdpebiRMn8sYbb3DTTTfRvHnz6/oadmxsLPHx8Xz11Vf4+PiQkZEB/PJ183r16gEwbNgwWrZsSVxcHABvvPEGPXv2pF27dmRnZ/Pee+9x/Phxnn766WvOISKO41ROEaPmJfLTsfMAPHFLK/7yQGe83DUMJSK/sLvczJ49m7lz5/Lkk09e9w+fNWsWcPFZjz/77DN+85vfAJCWlnbhSuTwy0kEf//735ORkUGjRo3o3r07W7ZsoXPnztedR0Rqt3X7shi7MInzhWU08HRj0iPdeCC0hdmxRKSWsXtCcZMmTdi+fTs33nhjdWWqVvZMSBKR2qHMauP9Vfv5eOMRALq29GVGdCQ3NL38yT5FxLnY8/lt9+UXnn76aeLj4685nIiIPX4+X8hjH2+9UGx+0+sGljzbS8VGRC7L7mGp4uJiPvnkE7777jtCQ0Nxd3ev8PiUKVOqLJyI1G2rUzMYt3g3OUVl+Hi58d6jodzXtbnZsUSklrumMxT/50zEKSkpFR7TNZ5EpCqUltuI+3Yvn20+BkBYcENmREcQ3Njb3GAi4hDsLjfr1q2rjhwiIgCknS1kxLwEdv/8y+VYnr6tDX++LwQPN7tH0UWkjtKV5ESk1liRfIoXF+8mr6Qcv3ruTB4SRt/OAWbHEhEHo3IjIqYrLrPy9jd7+XzbL5d36d66EdOiI2jZsJ7JyUTEEanciIipjp4pYER8AqkncwH4Y+8bef7eDri7ahhKRK6Nyo2ImObrXSeZsGQ3BaVWGtf3YPJjYdzZ0d/sWCLi4FRuRKTGFZdZmfjvPczbngZAjxsaMy06gkA/L5OTiYgzuKbjvp9//jm33norLVq04PjxX8bIP/zwQ7766qsqDScizudQVj6DZm5m3vY0LBYYeVc74n9/i4qNiFQZu8vNrFmzGDt2LPfffz/Z2dlYrVYAGjZsyIcffljV+UTEiXyZ8DMPzdjEvow8mjbw4J+/68Hz93bETfNrRKQK2f2OMn36dP72t7/x8ssv4+r636vw3nTTTSQnJ1dpOBFxDoWl5YxbtIuxC3dRWGolqm0TVoy6ndvbNzM7mog4Ibvn3Bw9epSIiIiLlnt6elJQUFAloUTEeRzIzCP2iwQOZuXjYoHRd3dgxF3tcHXRGc1FpHrYXW7atGlDUlISrVu3rrB85cqVdOrUqcqCiYhjMwyDRTt+5tWvUygus+Hv48nUoRFE3djE7Ggi4uTsLjdjx44lNjaW4uJiDMNg+/btzJs3j7i4OObMmVMdGUXEwRSUlPPy0mSWJZ0E4Pb2Tfng8XCaNvA0OZmI1AV2l5unn36aevXq8corr1BYWEhMTAwtWrRg6tSpDB06tDoyiogD2XMylxHxCRw5U4Cri4Wx93Tg2d434qJhKBGpIRbDMIxr3biwsJD8/Hz8/R3npFu5ubn4+fmRk5ODr6+v2XFEnIZhGMRvT2Piv/dQWm4j0NeL6TER3HxDY7OjiYgTsOfz+7pO4uft7Y23t/f1PIWIOIG84jImfJnM8t2nALizYzMmPxZO4/oeJicTkbrI7nJz9uxZXn31VdatW0dWVhY2m63C4+fOnauycCJS+6WcyCE2PoHjZwtxc7Hw5/s68vRtbTUMJSKmsbvcPPnkkxw6dIjhw4cTEBCAxaI3MJG6yDAM/rn1OG9/s5dSq42WDesxLTqC7q0bmR1NROo4u8vNDz/8wKZNmwgLC6uOPCLiAHKKynhx8W5WpmYA0LdTAO8PCaWht4ahRMR8dpebkJAQioqKqiOLiDiApPRsRsQn8PP5ItxdLUzo34nf3nqDjuKKSK1hd7n56KOPGD9+PK+++ipdu3bF3d29wuP6BpKIczIMg79vOsq7K/dRZjUIblyPGdGRhAU3NDuaiEgFdpebhg0bkpuby1133VVhuWEYWCyWCxfSFBHnkV1YyguLdvHd3iwA+ncNZNIjofjVc7/KliIiNc/ucvPEE0/g7u5OfHy8JhSL1AE7j59jZHwiJ3OK8XB14S8PdOL/9Wytv30RqbXsLjcpKSkkJibSsWPH6sgjIrWEzWbwyQ9HeG/Vfqw2gxuaeDMjJpKuLf3MjiYickV2l5ubbrqJ9PR0lRsRJ3Y2v4TnF+1i/f7TADwY1oJ3Hu6Kj5eGoUSk9rO73IwcOZLRo0czbtw4unXrdtGE4tDQ0CoLJyI1b/vRc4ycl0Bmbgmebi68/lAXht4crGEoEXEYdl9bysXF5eInsVgcZkKxri0lcmk2m8FH6w8xZc0BbAa0bVafmTGRdGquvxMRMV+1Xlvq6NGj1xxMRGqn03kljF2YxA8HzwAwOKIlbw7qSn3P67r8nIiIKex+52rdunV15BARk2w5dIbRC5I4nVeCl7sLbwzsypDuQRqGEhGHdU3/LDt8+DAffvghe/fuBaBz586MHj2aG2+8sUrDiUj1sdoMpq09yLTvD2IY0N6/AR89EUn7AB+zo4mIXJeLJ9BcxapVq+jcuTPbt28nNDSU0NBQfvzxR7p06cKaNWuqI6OIVLGs3GKemLONqWt/KTaP3RTE1yNuU7EREadg94TiiIgI+vXrx6RJkyosHz9+PKtXryYhIaFKA1Y1TSiWum7jgdM8tyCJswWleHu48vbDXXk4IsjsWCIiV2TP57fd5cbLy4vk5GTat29fYfmBAwcIDQ2luLjY/sQ1SOVG6qpyq40PvjvAR+sPYxgQEujDjJhI2vk3MDuaiMhVVeu3pZo1a0ZSUtJF5SYpKQl/f397n05EasCpnCJGz0ti+7FzAMTc0opXH+iMl7uryclERKqe3eXm97//Pc888wxHjhyhV69eAGzevJl3332XsWPHVnlAEbk+6/ZlMXZhEucLy2jg6Ubc4G48GNbC7FgiItXG7mEpwzD48MMPmTx5MidPngSgRYsWjBs3jlGjRtX6r49qWErqijKrjfdX7efjjUcA6NrSlxnRkdzQtL7JyURE7Fetc27+V15eHgA+Po7zDQuVG6kLTmQXMTI+gYS0bACeimrNSwM64emmYSgRcUzVOuemqKgIwzDw9vbGx8eH48eP8/e//53OnTtz7733XnNoEakaa/Zk8sKiXeQUleHj5cZfHwmlf7fmZscSEakxdpebgQMHMnjwYP74xz+SnZ1Njx498PDw4MyZM0yZMoVnn322OnKKyFWUltuY9O0+Pt38yyVSwoL8mBETSXBjb5OTiYjULLtP4peQkMDtt98OwOLFiwkMDOT48eP885//ZNq0aVUeUESuLv1cIUNmb7lQbIbf1oZFf+ylYiMidZLdR24KCwsvzLFZvXo1gwcPxsXFhZ49e3L8+PEqDygiV/Zt8in+vGQ3ecXl+NVz5/0hYdzTOcDsWCIiprH7yE27du1YtmwZ6enprFq16sI8m6ysLE3QFalBxWVWXv0qhWe/SCCvuJzIVg35ZtRtKjYiUufZXW5effVVXnjhBW644QZuueUWoqKigF+O4kRERFR5QBG52LEzBTwyawv/3PrL0dI/9G7Lgj9EEdRIw1AiInaXm0cffZS0tDR27NjBypUrLyy/++67+eCDD+x6rri4OG6++WZ8fHzw9/dn0KBB7N+//6rbLVq0iJCQELy8vOjWrRsrVqyw99cQcVhf7zrJA9M3kXoyl0be7nz2m5uZ0L8T7q52/zmLiDila3o3DAwMJCIiAheX/27eo0cPQkJC7HqeDRs2EBsby7Zt21izZg1lZWXce++9FBQUXHabLVu2EB0dzfDhw0lMTGTQoEEMGjSIlJSUa/lVRBxGcZmVCV8mM2peIvkl5fS4oTErRt/OnSG67ImIyP+6rpP4VbXTp0/j7+/Phg0buOOOOy65zuOPP05BQQHLly+/sKxnz56Eh4cze/bsq/4MncRPHNHh0/nEfpHAvow8LBaI7dOOMX3b46ajNSJSR1TrSfyqU05ODgCNGze+7Dpbt2696BpW/fr1Y9myZZdcv6SkhJKSkgv3c3Nzrz+oSA1amvgzLy9NobDUStMGHnzweDi3t29mdiwRkVqr1pQbm83GmDFjuPXWW+natetl18vIyCAgoOK3QQICAsjIyLjk+nFxcUycOLFKs4rUhKLSX74NtWjnzwBEtW3C1KHh+Pt6mZxMRKR2qzXHtGNjY0lJSWH+/PlV+rwTJkwgJyfnwi09Pb1Kn1+kOhzIzOOhGZtYtPNnLBYYfXd7/vX0LSo2IiKVUCuO3IwYMYLly5ezceNGgoKCrrhuYGAgmZmZFZZlZmYSGBh4yfU9PT3x9PSssqwi1ckwDBbt/JlXv0qhuMxGMx9Ppg4Np9eNTc2OJiLiMEw9cmMYBiNGjGDp0qV8//33tGnT5qrbREVFsXbt2grL1qxZc+F8OyKOqqCknLELd/HnxbspLrNxe/umrBh1u4qNiIidTD1yExsbS3x8PF999RU+Pj4X5s34+flRr149AIYNG0bLli2Ji4sDYPTo0fTu3ZvJkyczYMAA5s+fz44dO/jkk09M+z1ErtfeU7nExidw5HQBLhZ4/t6OPNv7RlxcLGZHExFxOKaWm1mzZgHQp0+fCss/++wzfvOb3wCQlpZW4Xw6vXr1Ij4+nldeeYWXXnqJ9u3bs2zZsitOQhaprQzDYN72dF7/dyql5TYCfb2YFh1BjzaX/8agiIhcWa06z01N0HlupLbIKy7jpaUp/HvXSQD6dGzGlMfCaVzfw+RkIiK1j8Oe50akrkg5kcOI+ASOnS3E1cXCn/t15Pe3t9UwlIhIFVC5EalBhmHw+bbjvLV8L6VWGy0b1mNadATdWzcyO5qIiNNQuRGpITlFZYxfsptvU36ZON+3UwDvDwmlobeGoUREqpLKjUgN2JWezYh5CaSfK8Ld1cL4/p343a03YLFoGEpEpKqp3IhUI8Mw+HTzMSZ9u5cyq0FQo3rMjIkkLLih2dFERJyWyo1INckuLOWFRbv5bu8vZ9S+r0sg7z4ail89d5OTiYg4N5UbkWqw8/h5Rs1L5ER2ER6uLrzyQCee7Nlaw1AiIjVA5UakCtlsBn/74QjvrdpPuc2gdRNvZsZE0rWln9nRRETqDJUbkSpyrqCU5xcmsW7/aQAeCG1O3OBu+HhpGEpEpCap3IhUge1HzzFqXiIZucV4uLnw+oNdiO4RrGEoERETqNyIXAebzWDWhsNMWXMAq82gbbP6zIyJpFNzXdpDRMQsKjci1+hMfgnPLUjih4NnAHg4oiVvDepKfU/9WYmImEnvwiLXYMvhM4yen8TpvBK83F14Y2BXhnQP0jCUiEgtoHIjYgerzWD69weZtvYgNgPa+zdg5hORdAjwMTuaiIj8H5UbkUrKyi1mzIIkthw+C8CQ7kFMHNgFbw/9GYmI1CZ6VxaphB8Onua5BUmcyS/F28OVtwZ1ZXBkkNmxRETkElRuRK6g3Grjw+8OMnP9IQwDQgJ9mBETSTv/BmZHExGRy1C5EbmMjJxiRs1LZPuxcwDE3NKKVx/ojJe7q8nJRETkSlRuRC5h3f4snl+4i3MFpTTwdOOdwd14KKyF2bFERKQSVG5E/keZ1cb7q/fz8YYjAHRp4cuMmEjaNK1vcjIREakslRuR/3Miu4hR8xLZefw8AMOiWvPS/Z00DCUi4mBUbkSANXsyeWHRLnKKyvDxcuOvj4TSv1tzs2OJiMg1ULmROq203Ma7K/fx901HAQgL8mN6dCStmnibnExERK6Vyo3UWennChkxL5Fd6dkA/O7WNozvH4KHm4u5wURE5Lqo3EidtDLlFOMW7yavuBxfLzfeHxLGvV0CzY4lIiJVQOVG6pSScivvfLOXf2w9DkBEq4ZMj44gqJGGoUREnIXKjdQZx84UMGJeAikncgH4Q++2vHBvR9xdNQwlIuJMVG6kTli++yTjlySTX1JOI293pjwWzp0h/mbHEhGRaqByI06tuMzKG8v3EP9jGgA339CIadERNPerZ3IyERGpLio34rQOn84n9osE9mXkYbHAn/rcyHN9O+CmYSgREaemciNOaVniCV5amkxhqZUm9T344PFw7ujQzOxYIiJSA1RuxKkUlVp5/etUFuxIB6Bn28ZMGxqBv6+XyclERKSmqNyI0ziYmUdsfAIHMvOxWGDUXe0ZdXd7XF0sZkcTEZEapHIjTmHRjnRe/SqVojIrzXw8mfp4OL3aNTU7loiImEDlRhxaQUk5f/kqhS8TTgBwe/umTHksnGY+niYnExERs6jciMPal5FL7BcJHD5dgIsFxt7TgT/1aYeLhqFEROo0lRtxOIZhMP+ndF7/OpWSchsBvp5MGxrBLW2bmB1NRERqAZUbcSh5xWW8tDSFf+86CUCfjs2YPCSMJg00DCUiIr9QuRGHkXIihxHxCRw7W4iri4Vx/TryzO1tNQwlIiIVqNxIrWcYBv/adpw3l++l1GqjhZ8X02Mi6N66sdnRRESkFlK5kVott7iM8Ut2syI5A4C+nfx5f0gYDb09TE4mIiK1lcqN1Fq7f84mNj6B9HNFuLtaePG+EIbf1gaLRcNQIiJyeSo3UusYhsFnm48R9+1eyqwGQY3qMSMmkvDghmZHExERB6ByI7VKTmEZ4xbvYvWeTADu6xLIu4+G4lfP3eRkIiLiKFRupNZISDvPyPhETmQX4eHqwssDOjEsqrWGoURExC4uZv7wjRs38uCDD9KiRQssFgvLli274vrr16/HYrFcdMvIyKiZwFItbDaDTzYe5rHZWzmRXUTrJt58+adePNXrBhUbERGxm6lHbgoKCggLC+N3v/sdgwcPrvR2+/fvx9fX98J9f3//6ognNeB8QSnPL9rF9/uyAHggtDlxg7vh46VhKBERuTamlpv+/fvTv39/u7fz9/enYcOGVR9IatRPx84xal4ip3KK8XBz4bUHOxPTo5WO1oiIyHVxyDk34eHhlJSU0LVrV15//XVuvfXWy65bUlJCSUnJhfu5ubk1EVGuwGYzmLXhMFPWHMBqM2jbtD4zYiLp3ML36huLiIhchalzbuzVvHlzZs+ezZIlS1iyZAnBwcH06dOHhISEy24TFxeHn5/fhVtwcHANJpZfO5NfwlOfbee9Vfux2gwejmjJv0fepmIjIiJVxmIYhmF2CACLxcLSpUsZNGiQXdv17t2bVq1a8fnnn1/y8UsduQkODiYnJ6fCvB2pflsPn2X0/ESy8krwcnfhjYe6MuSmIA1DiYjIVeXm5uLn51epz2+HHJb6Xz169GDTpk2XfdzT0xNPT10x2kxWm8GM7w8xde0BbAa092/AzCci6RDgY3Y0ERFxQg5fbpKSkmjevLnZMeQysvKKGTM/iS2HzwIwpHsQEwd2wdvD4V96IiJSS5n6CZOfn8+hQ4cu3D969ChJSUk0btyYVq1aMWHCBE6cOME///lPAD788EPatGlDly5dKC4uZs6cOXz//fesXr3arF9BrmDTwTOMWZDEmfwSvD1ceWtQVwZHBpkdS0REnJyp5WbHjh3ceeedF+6PHTsWgKeeeoq5c+dy6tQp0tLSLjxeWlrK888/z4kTJ/D29iY0NJTvvvuuwnOI+cqtNqauPciMdYcwDAgJ9GFGTCTt/BuYHU1EROqAWjOhuKbYMyFJ7JeRU8yo+YlsP3oOgOgerXjtwc54ubuanExERBxZnZpQLLXH+v1ZjF24i3MFpdT3cCXukVAeCmthdiwREaljVG7kupVZbUxZc4BZ6w8D0Lm5LzOfiKRN0/omJxMRkbpI5Uauy8nsIkbOS2Tn8fMADItqzUv3d9IwlIiImEblRq7Z2r2ZPL9oF9mFZfh4uvHuo6Hc301fyxcREXOp3IjdSstt/HXlPuZsOgpAaJAfM6IjadXE2+RkIiIiKjdip/RzhYyYl8iu9GwAfndrG8b3D8HDzaEuUyYiIk5M5UYqbWVKBn9evIvc4nJ8vdx4f0gY93YJNDuWiIhIBSo3clUl5VbiVuxj7pZjAES0asj06AiCGmkYSkREah+VG7mi42cLGBGfSPKJHAD+cEdbXujXEXdXDUOJiEjtpHIjl/XN7lOMX7KbvJJyGnm7M/mxMO4KCTA7loiIyBWp3MhFisusvPXNHv617Zfret18QyOmRUfQ3K+eyclERESuTuVGKjhyOp/Y+ET2nsrFYoE/9bmR5/p2wE3DUCIi4iBUbuSCr5JO8NKXyRSUWmlS34MPHg/njg7NzI4lIiJiF5UboajUysR/pzL/p3QAerZtzNShEQT4epmcTERExH4qN3Xcoaw8Yr9IZH9mHhYLjLqrPaPubo+ri8XsaCIiItdE5aYOW7zzZ/6yLIWiMivNfDyZ+ng4vdo1NTuWiIjIdVG5qYMKS8v5y7JUliT8DMBt7ZrywePhNPPxNDmZiIjI9VO5qWP2ZeQS+0UCh08X4GKBsfd04Nk+7TQMJSIiTkPlpo4wDIMFP6Xz2teplJTbCPD1ZNrQCG5p28TsaCIiIlVK5aYOyC8p5+WlyXyVdBKA3h2aMeWxMJo00DCUiIg4H5UbJ5d6MocR8YkcPVOAq4uFcf068sztbXHRMJSIiDgplRsnZRgG//oxjTeX76G03EYLPy+mx0TQvXVjs6OJiIhUK5UbJ5RbXMaEJcl8k3wKgL6d/Hnv0TAa1fcwOZmIiEj1U7lxMrt/zmZEfCJp5wpxc7Ewvn8Iw29rg8WiYSgREakbVG6chGEYzN1yjHdW7KXMahDUqB4zYiIJD25odjQREZEapXLjBHIKy/jzkl2sSs0EoF+XAP76aBh+9dxNTiYiIlLzVG4cXGLaeUbEJ3IiuwgPVxdeHtCJYVGtNQwlIiJ1lsqNgzIMgzk/HOXdlfsotxm0buLNjOhIugX5mR1NRETEVCo3Duh8QSkvLNrF2n1ZAAwIbU7c4G74emkYSkREROXGwew4do5R8xI5mVOMh5sLrz3YmZgerTQMJSIi8n9UbhyEzWYwe+NhJq8+gNVm0LZpfWbERNK5ha/Z0URERGoVlRsHcDa/hLELd7HhwGkABoW34K2Hu9HAU//7REREfk2fjrXctiNnGT0/kczcErzcXXjjoa4MuSlIw1AiIiKXoXJTS1ltBjPXHeLD7w5gM6CdfwNmxkTSMdDH7GgiIiK1mspNLZSVV8xzC5LYfOgsAI92D+KNgV3w9tD/LhERkavRp2Uts/nQGUbPT+JMfgn13F15a1BXHukeZHYsERERh6FyU0tYbQZT1x5k+vcHMQzoGODDzCciaeffwOxoIiIiDkXlphbIzC1m1LxEfjx6DoDoHsG89mAXvNxdTU4mIiLieFRuTLbhwGnGLkjibEEp9T1ceWdwNwaGtzQ7loiIiMNSuTFJudXG5DUHmLX+MACdm/sy84lI2jStb3IyERERx6ZyY4KT2UWMmpfIjuPnAXiyZ2teHtBJw1AiIiJVQOWmhn2/L5OxC3eRXViGj6cb7z4ayv3dmpsdS0RExGmo3NSQMquN91bt55ONRwAIDfJjRnQkrZp4m5xMRETEuajc1ID0c4WMnJdIUno2AL+99QbG9w/B003DUCIiIlVN5aaarUrNYNyiXeQWl+Pr5cZ7Q8Lo1yXQ7FgiIiJOy8XMH75x40YefPBBWrRogcViYdmyZVfdZv369URGRuLp6Um7du2YO3dutee8FiXlVib+O5U/fL6T3OJyIlo1ZMXo21VsREREqpmp5aagoICwsDBmzpxZqfWPHj3KgAEDuPPOO0lKSmLMmDE8/fTTrFq1qpqT2iftbCGPztrKZ5uPAfDMHW1Z+Icoghppfo2IiEh1M3VYqn///vTv37/S68+ePZs2bdowefJkADp16sSmTZv44IMP6NevX3XFtMuK5FO8uHg3eSXlNPJ2Z/JjYdwVEmB2LBERkTrDoebcbN26lb59+1ZY1q9fP8aMGXPZbUpKSigpKblwPzc3t1qyFZdZefubvXy+7TgAN7VuxPSYCJr71auWnyciIiKXZuqwlL0yMjIICKh4FCQgIIDc3FyKioouuU1cXBx+fn4XbsHBwdWS7aukExeKzZ/63Mj8Z3qq2IiIiJjAoY7cXIsJEyYwduzYC/dzc3OrpeAM6R7Mj0fPMTC8Jb07NKvy5xcREZHKcahyExgYSGZmZoVlmZmZ+Pr6Uq/epY+SeHp64unpWe3ZXFwsTHksvNp/joiIiFyZQw1LRUVFsXbt2grL1qxZQ1RUlEmJREREpLYxtdzk5+eTlJREUlIS8MtXvZOSkkhLSwN+GVIaNmzYhfX/+Mc/cuTIEf785z+zb98+PvroIxYuXMhzzz1nRnwRERGphUwtNzt27CAiIoKIiAgAxo4dS0REBK+++ioAp06dulB0ANq0acM333zDmjVrCAsLY/LkycyZM6fWfA1cREREzGcxDMMwO0RNys3Nxc/Pj5ycHHx9fc2OIyIiIpVgz+e3Q825EREREbkalRsRERFxKio3IiIi4lRUbkRERMSpqNyIiIiIU1G5EREREaeiciMiIiJOReVGREREnIrKjYiIiDgVh7oqeFX4zwmZc3NzTU4iIiIilfWfz+3KXFihzpWbvLw8AIKDg01OIiIiIvbKy8vDz8/viuvUuWtL2Ww2Tp48iY+PDxaLpUqfOzc3l+DgYNLT03XdqqvQvqo87avK076qPO0r+2h/VV517SvDMMjLy6NFixa4uFx5Vk2dO3Lj4uJCUFBQtf4MX19fvfgrSfuq8rSvKk/7qvK0r+yj/VV51bGvrnbE5j80oVhEREScisqNiIiIOBWVmyrk6enJa6+9hqenp9lRaj3tq8rTvqo87avK076yj/ZX5dWGfVXnJhSLiIiIc9ORGxEREXEqKjciIiLiVFRuRERExKmo3IiIiIhTUbmx08yZM7nhhhvw8vLilltuYfv27Vdcf9GiRYSEhODl5UW3bt1YsWJFDSU1nz37au7cuVgslgo3Ly+vGkxrno0bN/Lggw/SokULLBYLy5Ytu+o269evJzIyEk9PT9q1a8fcuXOrPWdtYO++Wr9+/UWvK4vFQkZGRs0ENklcXBw333wzPj4++Pv7M2jQIPbv33/V7erq+9W17K+6+p41a9YsQkNDL5ygLyoqim+//faK25jxulK5scOCBQsYO3Ysr732GgkJCYSFhdGvXz+ysrIuuf6WLVuIjo5m+PDhJCYmMmjQIAYNGkRKSkoNJ6959u4r+OVslqdOnbpwO378eA0mNk9BQQFhYWHMnDmzUusfPXqUAQMGcOedd5KUlMSYMWN4+umnWbVqVTUnNZ+9++o/9u/fX+G15e/vX00Ja4cNGzYQGxvLtm3bWLNmDWVlZdx7770UFBRcdpu6/H51LfsL6uZ7VlBQEJMmTWLnzp3s2LGDu+66i4EDB5KamnrJ9U17XRlSaT169DBiY2Mv3LdarUaLFi2MuLi4S67/2GOPGQMGDKiw7JZbbjH+8Ic/VGvO2sDeffXZZ58Zfn5+NZSu9gKMpUuXXnGdP//5z0aXLl0qLHv88ceNfv36VWOy2qcy+2rdunUGYJw/f75GMtVWWVlZBmBs2LDhsuvU5ferX6vM/tJ71n81atTImDNnziUfM+t1pSM3lVRaWsrOnTvp27fvhWUuLi707duXrVu3XnKbrVu3VlgfoF+/fpdd31lcy74CyM/Pp3Xr1gQHB1/xXwJ1XV19XV2P8PBwmjdvzj333MPmzZvNjlPjcnJyAGjcuPFl19Hr6r8qs79A71lWq5X58+dTUFBAVFTUJdcx63WlclNJZ86cwWq1EhAQUGF5QEDAZcfvMzIy7FrfWVzLvurYsSOffvopX331Ff/617+w2Wz06tWLn3/+uSYiO5TLva5yc3MpKioyKVXt1Lx5c2bPns2SJUtYsmQJwcHB9OnTh4SEBLOj1RibzcaYMWO49dZb6dq162XXq6vvV79W2f1Vl9+zkpOTadCgAZ6envzxj39k6dKldO7c+ZLrmvW6qnNXBZfaKSoqqkLz79WrF506deLjjz/mzTffNDGZOLKOHTvSsWPHC/d79erF4cOH+eCDD/j8889NTFZzYmNjSUlJYdOmTWZHcQiV3V91+T2rY8eOJCUlkZOTw+LFi3nqqafYsGHDZQuOGXTkppKaNm2Kq6srmZmZFZZnZmYSGBh4yW0CAwPtWt9ZXMu++jV3d3ciIiI4dOhQdUR0aJd7Xfn6+lKvXj2TUjmOHj161JnX1YgRI1i+fDnr1q0jKCjoiuvW1fer/2XP/vq1uvSe5eHhQbt27ejevTtxcXGEhYUxderUS65r1utK5aaSPDw86N69O2vXrr2wzGazsXbt2suONUZFRVVYH2DNmjWXXd9ZXMu++jWr1UpycjLNmzevrpgOq66+rqpKUlKS07+uDMNgxIgRLF26lO+//542bdpcdZu6/Lq6lv31a3X5Pctms1FSUnLJx0x7XVXrdGUnM3/+fMPT09OYO3eusWfPHuOZZ54xGjZsaGRkZBiGYRhPPvmkMX78+Avrb9682XBzczPef/99Y+/evcZrr71muLu7G8nJyWb9CjXG3n01ceJEY9WqVcbhw4eNnTt3GkOHDjW8vLyM1NRUs36FGpOXl2ckJiYaiYmJBmBMmTLFSExMNI4fP24YhmGMHz/eePLJJy+sf+TIEcPb29sYN26csXfvXmPmzJmGq6ursXLlSrN+hRpj77764IMPjGXLlhkHDx40kpOTjdGjRxsuLi7Gd999Z9avUCOeffZZw8/Pz1i/fr1x6tSpC7fCwsIL6+j96r+uZX/V1fes8ePHGxs2bDCOHj1q7N692xg/frxhsViM1atXG4ZRe15XKjd2mj59utGqVSvDw8PD6NGjh7Ft27YLj/Xu3dt46qmnKqy/cOFCo0OHDoaHh4fRpUsX45tvvqnhxOaxZ1+NGTPmwroBAQHG/fffbyQkJJiQuub95+vKv779Z/889dRTRu/evS/aJjw83PDw8DDatm1rfPbZZzWe2wz27qt3333XuPHGGw0vLy+jcePGRp8+fYzvv//enPA16FL7CKjwOtH71X9dy/6qq+9Zv/vd74zWrVsbHh4eRrNmzYy77777QrExjNrzurIYhmFU77EhERERkZqjOTciIiLiVFRuRERExKmo3IiIiIhTUbkRERERp6JyIyIiIk5F5UZEREScisqNiIiIOBWVGxEREXEqKjciIiLiVFRuRERExKmo3IiIiIhTUbkRERERp/L/AfP6s4EHq1M1AAAAAElFTkSuQmCC\n", 48 | "text/plain": [ 49 | "
" 50 | ] 51 | }, 52 | "metadata": {}, 53 | "output_type": "display_data" 54 | }, 55 | { 56 | "name": "stdout", 57 | "output_type": "stream", 58 | "text": [ 59 | "Error\n" 60 | ] 61 | }, 62 | { 63 | "ename": "ValueError", 64 | "evalue": "Test value error", 65 | "output_type": "error", 66 | "traceback": [ 67 | "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", 68 | "\u001b[1;31mValueError\u001b[0m Traceback (most recent call last)", 69 | "\u001b[1;32m\u001b[0m in \u001b[0;36m\u001b[1;34m\u001b[0m\n\u001b[0;32m 6\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 7\u001b[0m \u001b[0mprint\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;34m\"Error\"\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m----> 8\u001b[1;33m \u001b[1;32mraise\u001b[0m \u001b[0mValueError\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;34m\"Test value error\"\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m", 70 | "\u001b[1;31mValueError\u001b[0m: Test value error" 71 | ] 72 | } 73 | ], 74 | "source": [ 75 | "%matplotlib inline\n", 76 | "import matplotlib.pyplot as plt\n", 77 | "plt.plot([1,2,3,4])\n", 78 | "plt.ylabel('some numbers')\n", 79 | "plt.show()\n", 80 | "\n", 81 | "print(\"Error\")\n", 82 | "raise ValueError(\"Test value error\")" 83 | ] 84 | }, 85 | { 86 | "cell_type": "markdown", 87 | "metadata": {}, 88 | "source": [ 89 | "Cell with two stdouts, a stderr (warnning) and a string output." 90 | ] 91 | }, 92 | { 93 | "cell_type": "code", 94 | "execution_count": 2, 95 | "metadata": { 96 | "jupyter": { 97 | "source_hidden": true 98 | }, 99 | "tags": [] 100 | }, 101 | "outputs": [ 102 | { 103 | "name": "stdout", 104 | "output_type": "stream", 105 | "text": [ 106 | "Warnings\n", 107 | "after\n" 108 | ] 109 | }, 110 | { 111 | "name": "stderr", 112 | "output_type": "stream", 113 | "text": [ 114 | ":6: DeprecationWarning: deprecated\n", 115 | " warnings.warn(\"deprecated\", DeprecationWarning)\n", 116 | "stderr\n" 117 | ] 118 | }, 119 | { 120 | "data": { 121 | "text/plain": [ 122 | "array([[1, 2, 3],\n", 123 | " [4, 5, 6],\n", 124 | " [7, 8, 9]])" 125 | ] 126 | }, 127 | "execution_count": 2, 128 | "metadata": {}, 129 | "output_type": "execute_result" 130 | } 131 | ], 132 | "source": [ 133 | "import warnings\n", 134 | "import sys\n", 135 | "import numpy as np\n", 136 | "\n", 137 | "print(\"Warnings\")\n", 138 | "warnings.warn(\"deprecated\", DeprecationWarning)\n", 139 | "print(\"after\")\n", 140 | "print(\"stderr\", file=sys.stderr)\n", 141 | "\n", 142 | "a = np.array([[1,2,3], [4,5,6], [7,8,9]])\n", 143 | "a" 144 | ] 145 | }, 146 | { 147 | "cell_type": "markdown", 148 | "metadata": {}, 149 | "source": [ 150 | "Cell with the hidden source." 151 | ] 152 | }, 153 | { 154 | "cell_type": "code", 155 | "execution_count": 1, 156 | "metadata": { 157 | "jupyter": { 158 | "source_hidden": true 159 | }, 160 | "tags": [] 161 | }, 162 | "outputs": [ 163 | { 164 | "ename": "SyntaxError", 165 | "evalue": "invalid syntax (, line 1)", 166 | "output_type": "error", 167 | "traceback": [ 168 | "\u001b[1;36m File \u001b[1;32m\"\"\u001b[1;36m, line \u001b[1;32m1\u001b[0m\n\u001b[1;33m The source of this cell should be hidden\u001b[0m\n\u001b[1;37m ^\u001b[0m\n\u001b[1;31mSyntaxError\u001b[0m\u001b[1;31m:\u001b[0m invalid syntax\n" 169 | ] 170 | } 171 | ], 172 | "source": [ 173 | "The source of this cell should be hidden" 174 | ] 175 | }, 176 | { 177 | "cell_type": "markdown", 178 | "metadata": {}, 179 | "source": [ 180 | "Cell with the hidden outputc." 181 | ] 182 | }, 183 | { 184 | "cell_type": "code", 185 | "execution_count": 2, 186 | "metadata": { 187 | "collapsed": true, 188 | "jupyter": { 189 | "outputs_hidden": true 190 | }, 191 | "tags": [] 192 | }, 193 | "outputs": [ 194 | { 195 | "ename": "SyntaxError", 196 | "evalue": "invalid syntax (, line 1)", 197 | "output_type": "error", 198 | "traceback": [ 199 | "\u001b[1;36m File \u001b[1;32m\"\"\u001b[1;36m, line \u001b[1;32m1\u001b[0m\n\u001b[1;33m The output of this cell should be hidden.\u001b[0m\n\u001b[1;37m ^\u001b[0m\n\u001b[1;31mSyntaxError\u001b[0m\u001b[1;31m:\u001b[0m invalid syntax\n" 200 | ] 201 | } 202 | ], 203 | "source": [ 204 | "The output of this cell should be hidden." 205 | ] 206 | }, 207 | { 208 | "cell_type": "markdown", 209 | "metadata": {}, 210 | "source": [ 211 | "Cell with the hidden source and the hidden output." 212 | ] 213 | }, 214 | { 215 | "cell_type": "code", 216 | "execution_count": 4, 217 | "metadata": { 218 | "collapsed": true, 219 | "jupyter": { 220 | "outputs_hidden": true, 221 | "source_hidden": true 222 | }, 223 | "tags": [] 224 | }, 225 | "outputs": [ 226 | { 227 | "ename": "SyntaxError", 228 | "evalue": "invalid syntax (, line 1)", 229 | "output_type": "error", 230 | "traceback": [ 231 | "\u001b[1;36m File \u001b[1;32m\"\"\u001b[1;36m, line \u001b[1;32m1\u001b[0m\n\u001b[1;33m Bot the source and the output of the cell should be hidden\u001b[0m\n\u001b[1;37m ^\u001b[0m\n\u001b[1;31mSyntaxError\u001b[0m\u001b[1;31m:\u001b[0m invalid syntax\n" 232 | ] 233 | } 234 | ], 235 | "source": [ 236 | "Bot the source and the output of the cell should be hidden" 237 | ] 238 | }, 239 | { 240 | "cell_type": "markdown", 241 | "metadata": {}, 242 | "source": [ 243 | "Cell with scrolled and hidden output" 244 | ] 245 | }, 246 | { 247 | "cell_type": "code", 248 | "execution_count": 3, 249 | "metadata": { 250 | "collapsed": true, 251 | "jupyter": { 252 | "outputs_hidden": true 253 | }, 254 | "tags": [] 255 | }, 256 | "outputs": [ 257 | { 258 | "name": "stdout", 259 | "output_type": "stream", 260 | "text": [ 261 | "top\n", 262 | "\n", 263 | "\n", 264 | "Middle\n", 265 | "\n", 266 | "\n", 267 | "Bottom\n" 268 | ] 269 | } 270 | ], 271 | "source": [ 272 | "print('top\\n\\n\\nMiddle\\n\\n\\nBottom')" 273 | ] 274 | }, 275 | { 276 | "cell_type": "markdown", 277 | "metadata": {}, 278 | "source": [ 279 | "Cell with scrolled output not exceeding max height." 280 | ] 281 | }, 282 | { 283 | "cell_type": "code", 284 | "execution_count": 4, 285 | "metadata": { 286 | "scrolled": true, 287 | "tags": [] 288 | }, 289 | "outputs": [ 290 | { 291 | "name": "stdout", 292 | "output_type": "stream", 293 | "text": [ 294 | "top\n", 295 | "\n", 296 | "\n", 297 | " Bottom\n" 298 | ] 299 | } 300 | ], 301 | "source": [ 302 | "print('top\\n\\n\\n Bottom')" 303 | ] 304 | }, 305 | { 306 | "cell_type": "markdown", 307 | "metadata": {}, 308 | "source": [ 309 | "Cell with scrolled output exceeding max height." 310 | ] 311 | }, 312 | { 313 | "cell_type": "code", 314 | "execution_count": 5, 315 | "metadata": { 316 | "scrolled": true, 317 | "tags": [] 318 | }, 319 | "outputs": [ 320 | { 321 | "name": "stdout", 322 | "output_type": "stream", 323 | "text": [ 324 | "top\n", 325 | "\n", 326 | "\n", 327 | "\n", 328 | "\n", 329 | "\n", 330 | "\n", 331 | "\n", 332 | "\n", 333 | "\n", 334 | "\n", 335 | "\n", 336 | "\n", 337 | "\n", 338 | "\n", 339 | "\n", 340 | "\n", 341 | "\n", 342 | "\n", 343 | "\n", 344 | "\n", 345 | "\n", 346 | "\n", 347 | "\n", 348 | "\n", 349 | "\n", 350 | "\n", 351 | "\n", 352 | "\n", 353 | "\n", 354 | "\n", 355 | "\n", 356 | "\n", 357 | "\n", 358 | " Bottom\n" 359 | ] 360 | } 361 | ], 362 | "source": [ 363 | "print('top\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n Bottom')" 364 | ] 365 | }, 366 | { 367 | "cell_type": "markdown", 368 | "metadata": {}, 369 | "source": [ 370 | "Cell with html output." 371 | ] 372 | }, 373 | { 374 | "cell_type": "code", 375 | "execution_count": 6, 376 | "metadata": {}, 377 | "outputs": [ 378 | { 379 | "data": { 380 | "text/html": [ 381 | "\n", 382 | " \n", 389 | " " 390 | ], 391 | "text/plain": [ 392 | "" 393 | ] 394 | }, 395 | "execution_count": 6, 396 | "metadata": {}, 397 | "output_type": "execute_result" 398 | } 399 | ], 400 | "source": [ 401 | "from IPython.display import IFrame\n", 402 | "IFrame('https://cs231n.github.io/assets/conv-demo/index.html', width=792, height=700)" 403 | ] 404 | }, 405 | { 406 | "cell_type": "markdown", 407 | "metadata": {}, 408 | "source": [ 409 | "Empty cell." 410 | ] 411 | }, 412 | { 413 | "cell_type": "code", 414 | "execution_count": 22, 415 | "metadata": { 416 | "ExecuteTime": { 417 | "end_time": "2021-06-01T16:17:53.150485Z", 418 | "start_time": "2021-06-01T16:17:52.841368Z" 419 | } 420 | }, 421 | "outputs": [ 422 | { 423 | "data": { 424 | "image/svg+xml": [ 425 | "\n", 426 | "\n", 428 | "\n", 430 | "\n", 431 | "\n", 433 | "\n", 434 | "%3\n", 435 | "\n", 436 | "\n", 437 | "cluster445\n", 438 | "\n", 439 | "445\n", 440 | "\n", 441 | "\n", 442 | "\n", 443 | "beta_2\n", 444 | "\n", 445 | "beta_2\n", 446 | "~\n", 447 | "Normal\n", 448 | "\n", 449 | "\n", 450 | "\n", 451 | "logit\n", 452 | "\n", 453 | "logit\n", 454 | "~\n", 455 | "Bernoulli\n", 456 | "\n", 457 | "\n", 458 | "\n", 459 | "beta_2->logit\n", 460 | "\n", 461 | "\n", 462 | "\n", 463 | "\n", 464 | "\n", 465 | "beta_1\n", 466 | "\n", 467 | "beta_1\n", 468 | "~\n", 469 | "Normal\n", 470 | "\n", 471 | "\n", 472 | "\n", 473 | "beta_1->logit\n", 474 | "\n", 475 | "\n", 476 | "\n", 477 | "\n", 478 | "\n", 479 | "intercept\n", 480 | "\n", 481 | "intercept\n", 482 | "~\n", 483 | "Normal\n", 484 | "\n", 485 | "\n", 486 | "\n", 487 | "intercept->logit\n", 488 | "\n", 489 | "\n", 490 | "\n", 491 | "\n", 492 | "\n" 493 | ], 494 | "text/plain": [ 495 | "" 496 | ] 497 | }, 498 | "execution_count": 22, 499 | "metadata": {}, 500 | "output_type": "execute_result" 501 | } 502 | ], 503 | "source": [ 504 | "pm.model_to_graphviz(manual_logistic_model)" 505 | ] 506 | }, 507 | { 508 | "cell_type": "code", 509 | "execution_count": null, 510 | "metadata": {}, 511 | "outputs": [], 512 | "source": [] 513 | } 514 | ], 515 | "metadata": { 516 | "kernelspec": { 517 | "display_name": "Python 3", 518 | "language": "python", 519 | "name": "python3" 520 | }, 521 | "language_info": { 522 | "codemirror_mode": { 523 | "name": "ipython", 524 | "version": 3 525 | }, 526 | "file_extension": ".py", 527 | "mimetype": "text/x-python", 528 | "name": "python", 529 | "nbconvert_exporter": "python", 530 | "pygments_lexer": "ipython3", 531 | "version": "3.7.6rc1" 532 | } 533 | }, 534 | "nbformat": 4, 535 | "nbformat_minor": 4 536 | } 537 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "lib": [ 5 | "dom", 6 | "dom.iterable", 7 | "esnext" 8 | ], 9 | "allowJs": true, 10 | "skipLibCheck": true, 11 | "esModuleInterop": true, 12 | "allowSyntheticDefaultImports": true, 13 | "strict": true, 14 | "forceConsistentCasingInFileNames": true, 15 | "noFallthroughCasesInSwitch": true, 16 | "module": "esnext", 17 | "moduleResolution": "node", 18 | "resolveJsonModule": true, 19 | "isolatedModules": true, 20 | "noEmit": true, 21 | "jsx": "react-jsx" 22 | }, 23 | "include": [ 24 | "src/lib" 25 | ] 26 | } 27 | --------------------------------------------------------------------------------