├── .gitignore ├── .nojekyll ├── README.md └── doc ├── pub ├── ._part0000_web4sa_django.html ├── ._part0000_web4sa_flask.html ├── ._part0000_web4sa_plain.html ├── ._part0001_web4sa_django.html ├── ._part0001_web4sa_flask.html ├── ._part0001_web4sa_plain.html ├── ._part0002_web4sa_django.html ├── ._part0002_web4sa_flask.html ├── ._part0002_web4sa_plain.html ├── ._part0003_web4sa_django.html ├── ._part0003_web4sa_flask.html ├── ._part0003_web4sa_plain.html ├── ._part0004_web4sa_django.html ├── ._part0004_web4sa_flask.html ├── ._part0004_web4sa_plain.html ├── ._part0005_web4sa_django.html ├── ._part0005_web4sa_flask.html ├── ._part0005_web4sa_plain.html ├── ._part0006_web4sa_django.html ├── ._part0006_web4sa_flask.html ├── ._part0006_web4sa_plain.html ├── ._part0007_web4sa_django.html ├── ._part0007_web4sa_flask.html ├── ._part0007_web4sa_plain.html ├── ._part0008_web4sa_django.html ├── ._part0008_web4sa_flask.html ├── ._part0008_web4sa_plain.html ├── ._part0009_web4sa_django.html ├── ._part0009_web4sa_flask.html ├── ._part0009_web4sa_plain.html ├── ._part0010_web4sa_flask.html ├── ._part0010_web4sa_plain.html ├── ._part0011_web4sa_flask.html ├── ._part0011_web4sa_plain.html ├── ._part0012_web4sa_flask.html ├── ._part0012_web4sa_plain.html ├── ._part0013_web4sa_plain.html ├── ._part0014_web4sa_plain.html ├── ._part0015_web4sa_plain.html ├── ._part0016_web4sa_plain.html ├── ._part0017_web4sa_plain.html ├── ._web4sa_django000.html ├── ._web4sa_django001.html ├── ._web4sa_django002.html ├── ._web4sa_django003.html ├── ._web4sa_django004.html ├── ._web4sa_django005.html ├── ._web4sa_django006.html ├── ._web4sa_django007.html ├── ._web4sa_django008.html ├── ._web4sa_flask000.html ├── ._web4sa_flask001.html ├── ._web4sa_flask002.html ├── ._web4sa_flask003.html ├── ._web4sa_flask004.html ├── ._web4sa_flask005.html ├── ._web4sa_flask006.html ├── ._web4sa_flask007.html ├── ._web4sa_flask008.html ├── ._web4sa_flask009.html ├── ._web4sa_flask010.html ├── ._web4sa_flask011.html ├── ._web4sa_flask012.html ├── ._web4sa_flask013.html ├── ._web4sa_flask014.html ├── ._web4sa_flask015.html ├── ._web4sa_flask016.html ├── ._web4sa_flask017.html ├── ._web4sa_plain000.html ├── ._web4sa_plain001.html ├── ._web4sa_plain002.html ├── ._web4sa_plain003.html ├── ._web4sa_plain004.html ├── ._web4sa_plain005.html ├── ._web4sa_plain006.html ├── ._web4sa_plain007.html ├── ._web4sa_plain008.html ├── ._web4sa_plain009.html ├── ._web4sa_plain010.html ├── ._web4sa_plain011.html ├── ._web4sa_plain012.html ├── ._web4sa_plain013.html ├── ._web4sa_plain014.html ├── ._web4sa_plain015.html ├── ._web4sa_plain016.html ├── ._web4sa_plain017.html ├── ._web4sa_plain018.html ├── ._web4sa_plain019.html ├── ._web4sa_plain020.html ├── ._web4sa_plain021.html ├── ._web4sa_solarized000.html ├── ._web4sa_solarized001.html ├── ._web4sa_solarized002.html ├── ._web4sa_solarized003.html ├── ._web4sa_solarized004.html ├── ._web4sa_solarized005.html ├── ._web4sa_solarized006.html ├── ._web4sa_solarized007.html ├── ._web4sa_solarized008.html ├── ._web4sa_solarized009.html ├── ._web4sa_solarized010.html ├── ._web4sa_solarized011.html ├── ._web4sa_solarized012.html ├── ._web4sa_solarized013.html ├── ._web4sa_solarized014.html ├── ._web4sa_solarized015.html ├── ._web4sa_solarized016.html ├── ._web4sa_solarized017.html ├── ._web4sa_solarized018.html ├── ._web4sa_solarized019.html ├── ._web4sa_solarized020.html ├── ._web4sa_solarized021.html ├── fig-web4sa │ ├── Taylor_approx.png │ ├── Taylor_approx_exp2t.pdf │ ├── Taylor_approx_exp2t.png │ ├── gen_flask_gamma.png │ ├── hw1_django_input.png │ ├── hw1_django_output.png │ ├── hw1_flask_input.png │ ├── hw1_flask_output.png │ ├── hw2_django_output.png │ ├── hw2_flask_output.png │ ├── login_login.png │ ├── login_main.png │ ├── login_old.png │ ├── login_register.png │ ├── login_results.png │ ├── plot_formula.png │ ├── upload1.png │ ├── upload2.png │ ├── upload3.png │ ├── vib1_flask_bootstrap.png │ ├── vib1_flask_bootswatch_journal.png │ ├── vib1_flask_error1.png │ ├── vib1_flask_input.png │ ├── vib1_flask_latex.png │ ├── vib1_flask_output.png │ ├── vib1_flask_table2.png │ ├── vib2_flask_error1.png │ └── vib3_flask_gamma.png ├── index.html ├── sphinx-cbc │ ├── ._web4sa000.html │ ├── ._web4sa001.html │ ├── .buildinfo │ ├── _images │ │ ├── hw1_django_input.png │ │ ├── hw1_django_output.png │ │ ├── hw1_flask_input.png │ │ ├── hw1_flask_output.png │ │ ├── hw2_django_output.png │ │ ├── hw2_flask_output.png │ │ ├── vib1_flask_error1.png │ │ ├── vib1_flask_input.png │ │ ├── vib1_flask_latex.png │ │ ├── vib1_flask_output.png │ │ ├── vib1_flask_table2.png │ │ └── vib2_flask_error1.png │ ├── _sources │ │ ├── ._web4sa000.txt │ │ ├── ._web4sa001.txt │ │ └── index.txt │ ├── _static │ │ ├── ajax-loader.gif │ │ ├── basic.css │ │ ├── cbc_banner.png │ │ ├── cbc_logo.png │ │ ├── comment-bright.png │ │ ├── comment-close.png │ │ ├── comment.png │ │ ├── default.css │ │ ├── doctools.js │ │ ├── down-pressed.png │ │ ├── down.png │ │ ├── file.png │ │ ├── jquery.js │ │ ├── minus.png │ │ ├── plus.png │ │ ├── pygments.css │ │ ├── searchtools.js │ │ ├── sidebar.js │ │ ├── underscore.js │ │ ├── up-pressed.png │ │ ├── up.png │ │ └── websupport.js │ ├── genindex.html │ ├── index.html │ ├── objects.inv │ ├── search.html │ └── searchindex.js ├── web4sa.html ├── web4sa.pdf ├── web4sa_django.html ├── web4sa_flask.html ├── web4sa_plain.html ├── web4sa_plain_all.html └── web4sa_solarized.html ├── src └── web4sa │ ├── clean.sh │ ├── django_hw.do.txt │ ├── django_vib.do.txt │ ├── exer │ ├── Taylor_approx │ │ ├── compute.py │ │ ├── controller.py │ │ ├── model.py │ │ └── templates │ │ │ └── view.html │ ├── addmul │ │ ├── compute.py │ │ ├── controller.py │ │ └── model.py │ ├── gen_ext │ │ ├── compute.py │ │ ├── controller.py │ │ ├── model.py │ │ ├── templates │ │ │ ├── view.html │ │ │ ├── view_results.html │ │ │ └── view_results_default.py │ │ └── view.py │ └── plot_formula │ │ ├── README.txt │ │ ├── compute.py │ │ ├── controller.py │ │ ├── model.py │ │ └── templates │ │ └── view.html │ ├── exercises.do.txt │ ├── fig-web4sa │ ├── Taylor_approx.png │ ├── Taylor_approx_exp2t.pdf │ ├── Taylor_approx_exp2t.png │ ├── gen_flask_gamma.png │ ├── hw1_django_input.png │ ├── hw1_django_output.png │ ├── hw1_flask_input.png │ ├── hw1_flask_output.png │ ├── hw2_django_output.png │ ├── hw2_flask_output.png │ ├── login_main.png │ ├── login_register.png │ ├── plot_formula.png │ ├── upload1.png │ ├── upload2.png │ ├── upload3.png │ ├── vib1_flask_bootstrap.png │ ├── vib1_flask_bootswatch_journal.png │ ├── vib1_flask_error1.png │ ├── vib1_flask_input.png │ ├── vib1_flask_latex.png │ ├── vib1_flask_output.png │ ├── vib1_flask_table2.png │ └── vib2_flask_error1.png │ ├── flask_hw.do.txt │ ├── flask_vib.do.txt │ ├── html_templates │ ├── template_django.html │ ├── template_flask.html │ └── template_flask_django.html │ ├── index.do.txt │ ├── intro.do.txt │ ├── links.do.txt │ ├── make.sh │ ├── publish.sh │ ├── slides-web4sa │ ├── django_hw.do.txt │ ├── django_vib.do.txt │ ├── flask_hw.do.txt │ ├── flask_vib.do.txt │ ├── intro.do.txt │ └── links.do.txt │ ├── slides_web4sa.do.txt │ ├── src-web4sa │ ├── apps │ │ ├── django_apps │ │ │ ├── hw1 │ │ │ │ ├── __init__.py │ │ │ │ ├── compute.py │ │ │ │ ├── models.py │ │ │ │ ├── templates │ │ │ │ │ └── hw1.html │ │ │ │ ├── tests.py │ │ │ │ └── views.py │ │ │ ├── hw2 │ │ │ │ ├── __init__.py │ │ │ │ ├── compute.py │ │ │ │ ├── models.py │ │ │ │ ├── templates │ │ │ │ │ └── hw2.html │ │ │ │ └── views.py │ │ │ ├── vib1 │ │ │ │ ├── __init__.py │ │ │ │ ├── compute.py │ │ │ │ ├── models.py │ │ │ │ ├── templates │ │ │ │ │ └── vib1.html │ │ │ │ └── views.py │ │ │ └── vib2 │ │ │ │ ├── __init__.py │ │ │ │ ├── compute.py │ │ │ │ ├── models.py │ │ │ │ ├── templates │ │ │ │ └── vib2.html │ │ │ │ └── views.py │ │ ├── flask_apps │ │ │ ├── gen │ │ │ │ ├── compute.py │ │ │ │ ├── controller.py │ │ │ │ ├── model.py │ │ │ │ └── templates │ │ │ │ │ ├── view.html │ │ │ │ │ ├── view_results.html │ │ │ │ │ └── view_results_default.html │ │ │ ├── hw1 │ │ │ │ ├── compute.py │ │ │ │ ├── controller.py │ │ │ │ └── templates │ │ │ │ │ ├── view_input.html │ │ │ │ │ └── view_output.html │ │ │ ├── hw2 │ │ │ │ ├── compute.py │ │ │ │ ├── controller.py │ │ │ │ └── templates │ │ │ │ │ └── view.html │ │ │ ├── hw3 │ │ │ │ ├── compute.py │ │ │ │ ├── controller.py │ │ │ │ ├── model.py │ │ │ │ └── templates │ │ │ │ │ └── view.html │ │ │ ├── login │ │ │ │ ├── _generate_app.py │ │ │ │ ├── app.py │ │ │ │ ├── compute.py │ │ │ │ ├── controller.py │ │ │ │ ├── db_models.py │ │ │ │ └── forms.py │ │ │ ├── upload │ │ │ │ ├── compute.py │ │ │ │ ├── controller.py │ │ │ │ ├── model.py │ │ │ │ └── testfile.dat │ │ │ ├── vib1 │ │ │ │ ├── compute.py │ │ │ │ ├── controller.py │ │ │ │ ├── model.py │ │ │ │ ├── static │ │ │ │ │ └── basic.css │ │ │ │ └── templates │ │ │ │ │ ├── view.html │ │ │ │ │ ├── view_bootstrap.html │ │ │ │ │ ├── view_css.html │ │ │ │ │ ├── view_errcheck.html │ │ │ │ │ ├── view_flask_bootstrap.html │ │ │ │ │ ├── view_plain.html │ │ │ │ │ ├── view_table.html │ │ │ │ │ └── view_tex.html │ │ │ ├── vib2 │ │ │ │ ├── compute.py │ │ │ │ ├── controller.py │ │ │ │ ├── model.py │ │ │ │ └── templates │ │ │ │ │ └── view.html │ │ │ └── vib3 │ │ │ │ ├── compute.py │ │ │ │ ├── controller.py │ │ │ │ └── model.py │ │ └── py_apps │ │ │ ├── hw_mvc │ │ │ ├── compute.py │ │ │ ├── controller.py │ │ │ ├── model.py │ │ │ └── view.py │ │ │ └── hw_orig │ │ │ └── hw.py │ └── django_project │ │ ├── django_project │ │ ├── __init__.py │ │ ├── settings.py │ │ ├── urls.py │ │ └── wsgi.py │ │ └── manage.py │ └── web4sa.do.txt └── web ├── images ├── body-bg.png ├── highlight-bg.jpg ├── hr.png ├── octocat-icon.png ├── tar-gz-icon.png └── zip-icon.png ├── index.html ├── javascripts └── main.js ├── params.json └── stylesheets ├── print.css ├── pygment_trac.css └── stylesheet.css /.gitignore: -------------------------------------------------------------------------------- 1 | syntax: glob 2 | # compiled files: 3 | *.o 4 | *.so 5 | *.a 6 | # temporary files: 7 | build 8 | *.bak 9 | *.swp 10 | *~ 11 | .*~ 12 | *.old 13 | tmp* 14 | temp* 15 | .#* 16 | \#* 17 | # tex files: 18 | *.log 19 | *.dvi 20 | *.aux 21 | *.blg 22 | *.bbl 23 | *.idx 24 | *.ilg 25 | *.ind 26 | *.loe 27 | *.nav 28 | *.out 29 | *.toc 30 | *.snm 31 | *.vrb 32 | # eclipse files: 33 | *.cproject 34 | *.project 35 | # misc: 36 | .DS_Store 37 | .idea 38 | __pycache__ 39 | _minted-* 40 | # doconce: 41 | .*_html_file_collection 42 | .*.exerinfo 43 | .*.copyright 44 | sphinx-rootdir 45 | Trash 46 | -------------------------------------------------------------------------------- /.nojekyll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hplgit/web4sciapps/8d225ced1928e0706c43044429325c8ff9b01e76/.nojekyll -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | web4sciapps 2 | =========== 3 | 4 | Examples on using web frameworks for making scientific applications. -------------------------------------------------------------------------------- /doc/pub/._part0005_web4sa_plain.html: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 36 | 37 | 38 | 39 | 129 | 130 | 131 | 132 | 133 | 134 | 142 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | previous 155 | 156 | next 157 | 158 | 159 |

160 | 161 | 162 |

Troubleshooting

163 | 164 |

165 | Address already in use. 166 | You can easily kill the Flask application and restart it, but sometimes 167 | you will get an error that the address is already in use. 168 | To recover from this problem, run the lsof program to see which program 169 | that applies the 5000 port (Flask runs its server on http://127.0.0.1:5000, 170 | which means that it uses the 5000 port). Find the PID of the program 171 | that occupies the port and force abortion of that program: 172 | 173 |

174 | 175 | 176 |

Terminal> lsof -i :5000
177 | COMMAND   PID USER   FD   TYPE  DEVICE SIZE/OFF NODE NAME
178 | python  48824  hpl    3u  IPv4 1128848      0t0  TCP ...
179 | Terminal> kill -9 48824
180 | 
181 |

182 | You are now ready to restart a Flask application. 183 | 184 |

185 |

186 | 187 | previous 188 | 189 | next 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | -------------------------------------------------------------------------------- /doc/pub/._part0008_web4sa_django.html: -------------------------------------------------------------------------------- 1 | 2 | 31 | 32 | 33 | 34 | 35 | 36 | 44 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | previous 56 |

57 | 58 | 59 |

Exercises

60 | 61 |

62 | 63 | 64 |

Exercise 1: Add two numbers

65 | 66 |

67 | Make a web application that reads two numbers from a web page, 68 | adds the numbers, and prints the sum in a new web page. 69 | Package the necessary files that constitute the application 70 | in a tar file. 71 | Filename: add2.tar.gz. 72 | 73 |

74 | 75 | 76 |

77 | 78 | previous 79 | 80 | 81 | -------------------------------------------------------------------------------- /doc/pub/._web4sa_django002.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 16 | 17 | 18 | 19 | Using Django for Scientific Web Applications 20 | 21 |

22 |
23 | 26 |
27 | 32 |
33 |
34 |
35 | 36 | 37 |
38 | 50 | 51 |
52 | 53 | 54 | 104 | 105 | 106 | 107 | 108 | 109 | 117 | 120 | 121 | 122 | 123 | 124 | 125 | 126 |

A very simple application

127 | 128 |

129 | We shall start with the simplest possible application, 130 | a "scientific hello world program", where the 131 | task is to read a number and write out "Hello, World!" followed by 132 | the sine of the number. This application has one input variable and 133 | a line of text as output. 134 | 135 |

136 | Our first implementation reads the input from the command 137 | line and writes the results to the terminal window: 138 | 139 |

140 | 141 | 142 |

#!/usr/bin/env python
143 | import sys, math
144 | r = float(sys.argv[1])
145 | s = math.sin(r)
146 | print 'Hello, World! sin(%g)=%g' % (r, s)
147 | 
148 |

149 | In the terminal we can exemplify the program 150 | 151 |

152 | 153 | 154 |

Terminal> python hw.py 1.2
155 | Hello, World! sin(1.2)=0.932039
156 | 
157 |

158 | The task of the web version of this program is to read the r 159 | variable from a web page, compute the sine, 160 | and write out a new web page with the resulting text. 161 | 162 |

163 |

164 | 165 |

173 | 174 | 175 | 176 |
177 | 178 | 184 |
185 | 186 | 187 | 188 | -------------------------------------------------------------------------------- /doc/pub/._web4sa_django007.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 16 | 17 | 18 | 19 | Using Django for Scientific Web Applications 20 | 21 |
22 |
23 | 26 |
27 | 32 |
33 |
34 |
35 | 36 | 37 |
38 | 50 | 51 |
52 | 53 | 54 | 104 | 105 | 106 | 107 | 108 | 109 | 117 | 120 | 121 | 122 | 123 | 124 | 125 | 126 |

Resources

127 | 128 |

129 | Below are some resources for accounts and login with Django as well as 130 | utilization of Bootstrap styles in the views. 131 | 132 |

139 | 140 |

141 | 142 |

150 | 151 | 152 | 153 |
154 | 155 | 161 |
162 | 163 | 164 | 165 | -------------------------------------------------------------------------------- /doc/pub/fig-web4sa/Taylor_approx.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hplgit/web4sciapps/8d225ced1928e0706c43044429325c8ff9b01e76/doc/pub/fig-web4sa/Taylor_approx.png -------------------------------------------------------------------------------- /doc/pub/fig-web4sa/Taylor_approx_exp2t.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hplgit/web4sciapps/8d225ced1928e0706c43044429325c8ff9b01e76/doc/pub/fig-web4sa/Taylor_approx_exp2t.pdf -------------------------------------------------------------------------------- /doc/pub/fig-web4sa/Taylor_approx_exp2t.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hplgit/web4sciapps/8d225ced1928e0706c43044429325c8ff9b01e76/doc/pub/fig-web4sa/Taylor_approx_exp2t.png -------------------------------------------------------------------------------- /doc/pub/fig-web4sa/gen_flask_gamma.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hplgit/web4sciapps/8d225ced1928e0706c43044429325c8ff9b01e76/doc/pub/fig-web4sa/gen_flask_gamma.png -------------------------------------------------------------------------------- /doc/pub/fig-web4sa/hw1_django_input.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hplgit/web4sciapps/8d225ced1928e0706c43044429325c8ff9b01e76/doc/pub/fig-web4sa/hw1_django_input.png -------------------------------------------------------------------------------- /doc/pub/fig-web4sa/hw1_django_output.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hplgit/web4sciapps/8d225ced1928e0706c43044429325c8ff9b01e76/doc/pub/fig-web4sa/hw1_django_output.png -------------------------------------------------------------------------------- /doc/pub/fig-web4sa/hw1_flask_input.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hplgit/web4sciapps/8d225ced1928e0706c43044429325c8ff9b01e76/doc/pub/fig-web4sa/hw1_flask_input.png -------------------------------------------------------------------------------- /doc/pub/fig-web4sa/hw1_flask_output.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hplgit/web4sciapps/8d225ced1928e0706c43044429325c8ff9b01e76/doc/pub/fig-web4sa/hw1_flask_output.png -------------------------------------------------------------------------------- /doc/pub/fig-web4sa/hw2_django_output.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hplgit/web4sciapps/8d225ced1928e0706c43044429325c8ff9b01e76/doc/pub/fig-web4sa/hw2_django_output.png -------------------------------------------------------------------------------- /doc/pub/fig-web4sa/hw2_flask_output.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hplgit/web4sciapps/8d225ced1928e0706c43044429325c8ff9b01e76/doc/pub/fig-web4sa/hw2_flask_output.png -------------------------------------------------------------------------------- /doc/pub/fig-web4sa/login_login.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hplgit/web4sciapps/8d225ced1928e0706c43044429325c8ff9b01e76/doc/pub/fig-web4sa/login_login.png -------------------------------------------------------------------------------- /doc/pub/fig-web4sa/login_main.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hplgit/web4sciapps/8d225ced1928e0706c43044429325c8ff9b01e76/doc/pub/fig-web4sa/login_main.png -------------------------------------------------------------------------------- /doc/pub/fig-web4sa/login_old.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hplgit/web4sciapps/8d225ced1928e0706c43044429325c8ff9b01e76/doc/pub/fig-web4sa/login_old.png -------------------------------------------------------------------------------- /doc/pub/fig-web4sa/login_register.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hplgit/web4sciapps/8d225ced1928e0706c43044429325c8ff9b01e76/doc/pub/fig-web4sa/login_register.png -------------------------------------------------------------------------------- /doc/pub/fig-web4sa/login_results.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hplgit/web4sciapps/8d225ced1928e0706c43044429325c8ff9b01e76/doc/pub/fig-web4sa/login_results.png -------------------------------------------------------------------------------- /doc/pub/fig-web4sa/plot_formula.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hplgit/web4sciapps/8d225ced1928e0706c43044429325c8ff9b01e76/doc/pub/fig-web4sa/plot_formula.png -------------------------------------------------------------------------------- /doc/pub/fig-web4sa/upload1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hplgit/web4sciapps/8d225ced1928e0706c43044429325c8ff9b01e76/doc/pub/fig-web4sa/upload1.png -------------------------------------------------------------------------------- /doc/pub/fig-web4sa/upload2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hplgit/web4sciapps/8d225ced1928e0706c43044429325c8ff9b01e76/doc/pub/fig-web4sa/upload2.png -------------------------------------------------------------------------------- /doc/pub/fig-web4sa/upload3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hplgit/web4sciapps/8d225ced1928e0706c43044429325c8ff9b01e76/doc/pub/fig-web4sa/upload3.png -------------------------------------------------------------------------------- /doc/pub/fig-web4sa/vib1_flask_bootstrap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hplgit/web4sciapps/8d225ced1928e0706c43044429325c8ff9b01e76/doc/pub/fig-web4sa/vib1_flask_bootstrap.png -------------------------------------------------------------------------------- /doc/pub/fig-web4sa/vib1_flask_bootswatch_journal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hplgit/web4sciapps/8d225ced1928e0706c43044429325c8ff9b01e76/doc/pub/fig-web4sa/vib1_flask_bootswatch_journal.png -------------------------------------------------------------------------------- /doc/pub/fig-web4sa/vib1_flask_error1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hplgit/web4sciapps/8d225ced1928e0706c43044429325c8ff9b01e76/doc/pub/fig-web4sa/vib1_flask_error1.png -------------------------------------------------------------------------------- /doc/pub/fig-web4sa/vib1_flask_input.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hplgit/web4sciapps/8d225ced1928e0706c43044429325c8ff9b01e76/doc/pub/fig-web4sa/vib1_flask_input.png -------------------------------------------------------------------------------- /doc/pub/fig-web4sa/vib1_flask_latex.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hplgit/web4sciapps/8d225ced1928e0706c43044429325c8ff9b01e76/doc/pub/fig-web4sa/vib1_flask_latex.png -------------------------------------------------------------------------------- /doc/pub/fig-web4sa/vib1_flask_output.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hplgit/web4sciapps/8d225ced1928e0706c43044429325c8ff9b01e76/doc/pub/fig-web4sa/vib1_flask_output.png -------------------------------------------------------------------------------- /doc/pub/fig-web4sa/vib1_flask_table2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hplgit/web4sciapps/8d225ced1928e0706c43044429325c8ff9b01e76/doc/pub/fig-web4sa/vib1_flask_table2.png -------------------------------------------------------------------------------- /doc/pub/fig-web4sa/vib2_flask_error1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hplgit/web4sciapps/8d225ced1928e0706c43044429325c8ff9b01e76/doc/pub/fig-web4sa/vib2_flask_error1.png -------------------------------------------------------------------------------- /doc/pub/fig-web4sa/vib3_flask_gamma.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hplgit/web4sciapps/8d225ced1928e0706c43044429325c8ff9b01e76/doc/pub/fig-web4sa/vib3_flask_gamma.png -------------------------------------------------------------------------------- /doc/pub/index.html: -------------------------------------------------------------------------------- 1 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | Using Web Frameworks for Scientific Applications 12 | 13 | 14 | 15 | 18 | 19 | 20 | 21 | 22 | 25 | 26 | 27 | 28 | 29 |
30 | 31 |

 

 

 

32 | 33 | 34 | 35 | 36 | 37 |

Using Web Frameworks for Scientific Applications

38 | 39 |

40 | 41 | 42 |

43 | Hans Petter Langtangen [1] 44 |
45 | 46 |
47 | Anders Johansen [2] 48 |
49 | 50 |

51 | 52 | 53 |

[1] Center for Biomedical Computing, Simula Research Laboratory and Department of Informatics, University of Oslo
54 |
[2] Center for Biomedical Computing, Simula Research Laboratory
55 |
56 |

57 |

Oct 11, 2015

58 |
59 |

60 | 61 | 62 |

70 | 71 | 72 | 73 | 74 |
75 | 76 | 77 | 78 | 79 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | -------------------------------------------------------------------------------- /doc/pub/sphinx-cbc/._web4sa000.html: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | Using Web Frameworks for Scientific Applications 11 | 12 | 13 | 14 | 15 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 57 | 58 | 59 | 60 | 75 | 76 |
77 |
78 |
79 |
80 | 81 |
82 |

Using Web Frameworks for Scientific Applications

83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 |
Authors:Hans Petter Langtangen, Anders E. Johansen
Date:Oct 11, 2015
93 |
94 | 95 | 96 |
97 |
98 |
99 | 134 |
135 |
136 | 151 |
152 | 158 |
159 | 160 | 161 | -------------------------------------------------------------------------------- /doc/pub/sphinx-cbc/.buildinfo: -------------------------------------------------------------------------------- 1 | # Sphinx build info version 1 2 | # This file hashes the configuration used when building these files. When it is not found, a full rebuild will be done. 3 | config: 55852d421c7b5dd40a3eb6329928b707 4 | tags: 645f666f9bcd5a90fca523b33c5a78b7 5 | -------------------------------------------------------------------------------- /doc/pub/sphinx-cbc/_images/hw1_django_input.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hplgit/web4sciapps/8d225ced1928e0706c43044429325c8ff9b01e76/doc/pub/sphinx-cbc/_images/hw1_django_input.png -------------------------------------------------------------------------------- /doc/pub/sphinx-cbc/_images/hw1_django_output.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hplgit/web4sciapps/8d225ced1928e0706c43044429325c8ff9b01e76/doc/pub/sphinx-cbc/_images/hw1_django_output.png -------------------------------------------------------------------------------- /doc/pub/sphinx-cbc/_images/hw1_flask_input.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hplgit/web4sciapps/8d225ced1928e0706c43044429325c8ff9b01e76/doc/pub/sphinx-cbc/_images/hw1_flask_input.png -------------------------------------------------------------------------------- /doc/pub/sphinx-cbc/_images/hw1_flask_output.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hplgit/web4sciapps/8d225ced1928e0706c43044429325c8ff9b01e76/doc/pub/sphinx-cbc/_images/hw1_flask_output.png -------------------------------------------------------------------------------- /doc/pub/sphinx-cbc/_images/hw2_django_output.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hplgit/web4sciapps/8d225ced1928e0706c43044429325c8ff9b01e76/doc/pub/sphinx-cbc/_images/hw2_django_output.png -------------------------------------------------------------------------------- /doc/pub/sphinx-cbc/_images/hw2_flask_output.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hplgit/web4sciapps/8d225ced1928e0706c43044429325c8ff9b01e76/doc/pub/sphinx-cbc/_images/hw2_flask_output.png -------------------------------------------------------------------------------- /doc/pub/sphinx-cbc/_images/vib1_flask_error1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hplgit/web4sciapps/8d225ced1928e0706c43044429325c8ff9b01e76/doc/pub/sphinx-cbc/_images/vib1_flask_error1.png -------------------------------------------------------------------------------- /doc/pub/sphinx-cbc/_images/vib1_flask_input.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hplgit/web4sciapps/8d225ced1928e0706c43044429325c8ff9b01e76/doc/pub/sphinx-cbc/_images/vib1_flask_input.png -------------------------------------------------------------------------------- /doc/pub/sphinx-cbc/_images/vib1_flask_latex.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hplgit/web4sciapps/8d225ced1928e0706c43044429325c8ff9b01e76/doc/pub/sphinx-cbc/_images/vib1_flask_latex.png -------------------------------------------------------------------------------- /doc/pub/sphinx-cbc/_images/vib1_flask_output.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hplgit/web4sciapps/8d225ced1928e0706c43044429325c8ff9b01e76/doc/pub/sphinx-cbc/_images/vib1_flask_output.png -------------------------------------------------------------------------------- /doc/pub/sphinx-cbc/_images/vib1_flask_table2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hplgit/web4sciapps/8d225ced1928e0706c43044429325c8ff9b01e76/doc/pub/sphinx-cbc/_images/vib1_flask_table2.png -------------------------------------------------------------------------------- /doc/pub/sphinx-cbc/_images/vib2_flask_error1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hplgit/web4sciapps/8d225ced1928e0706c43044429325c8ff9b01e76/doc/pub/sphinx-cbc/_images/vib2_flask_error1.png -------------------------------------------------------------------------------- /doc/pub/sphinx-cbc/_sources/._web4sa000.txt: -------------------------------------------------------------------------------- 1 | .. Automatically generated Sphinx-extended reStructuredText file from DocOnce source 2 | (https://github.com/hplgit/doconce/) 3 | 4 | .. Document title: 5 | 6 | Using Web Frameworks for Scientific Applications 7 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 8 | 9 | :Authors: Hans Petter Langtangen, Anders E. Johansen 10 | :Date: Oct 11, 2015 11 | 12 | -------------------------------------------------------------------------------- /doc/pub/sphinx-cbc/_sources/index.txt: -------------------------------------------------------------------------------- 1 | 2 | .. Master file automatically created by doconce sphinx_dir 3 | 4 | Using Web Frameworks for Scientific Applications 5 | ================================================ 6 | 7 | Contents: 8 | 9 | .. toctree:: 10 | :maxdepth: 2 11 | 12 | ._web4sa000 13 | ._web4sa001 14 | ._web4sa002 15 | ._web4sa003 16 | ._web4sa004 17 | ._web4sa005 18 | ._web4sa006 19 | ._web4sa007 20 | 21 | 22 | Index 23 | ===== 24 | 25 | * :ref:`genindex` 26 | -------------------------------------------------------------------------------- /doc/pub/sphinx-cbc/_static/ajax-loader.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hplgit/web4sciapps/8d225ced1928e0706c43044429325c8ff9b01e76/doc/pub/sphinx-cbc/_static/ajax-loader.gif -------------------------------------------------------------------------------- /doc/pub/sphinx-cbc/_static/cbc_banner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hplgit/web4sciapps/8d225ced1928e0706c43044429325c8ff9b01e76/doc/pub/sphinx-cbc/_static/cbc_banner.png -------------------------------------------------------------------------------- /doc/pub/sphinx-cbc/_static/cbc_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hplgit/web4sciapps/8d225ced1928e0706c43044429325c8ff9b01e76/doc/pub/sphinx-cbc/_static/cbc_logo.png -------------------------------------------------------------------------------- /doc/pub/sphinx-cbc/_static/comment-bright.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hplgit/web4sciapps/8d225ced1928e0706c43044429325c8ff9b01e76/doc/pub/sphinx-cbc/_static/comment-bright.png -------------------------------------------------------------------------------- /doc/pub/sphinx-cbc/_static/comment-close.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hplgit/web4sciapps/8d225ced1928e0706c43044429325c8ff9b01e76/doc/pub/sphinx-cbc/_static/comment-close.png -------------------------------------------------------------------------------- /doc/pub/sphinx-cbc/_static/comment.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hplgit/web4sciapps/8d225ced1928e0706c43044429325c8ff9b01e76/doc/pub/sphinx-cbc/_static/comment.png -------------------------------------------------------------------------------- /doc/pub/sphinx-cbc/_static/default.css: -------------------------------------------------------------------------------- 1 | /* 2 | * default.css_t 3 | * ~~~~~~~~~~~~~ 4 | * 5 | * Sphinx stylesheet -- default theme. 6 | * 7 | * :copyright: Copyright 2007-2011 by the Sphinx team, see AUTHORS. 8 | * :license: BSD, see LICENSE for details. 9 | * 10 | */ 11 | 12 | @import url("basic.css"); 13 | 14 | /* -- page layout ----------------------------------------------------------- */ 15 | 16 | body { 17 | font-family: sans-serif; 18 | font-size: 100%; 19 | background-color: #ffffff; 20 | color: #000; 21 | margin: 0; 22 | padding: 0; 23 | } 24 | 25 | div.document { 26 | background-color: #ffffff; 27 | } 28 | 29 | div.documentwrapper { 30 | float: left; 31 | width: 100%; 32 | } 33 | 34 | div.bodywrapper { 35 | margin: 0 0 0 230px; 36 | } 37 | 38 | div.body { 39 | background-color: #ffffff; 40 | color: #000000; 41 | padding: 0 20px 30px 20px; 42 | } 43 | div.bodywrapper { 44 | margin: 0 230px 0 0; 45 | } 46 | 47 | div.footer { 48 | color: #8A0808; 49 | width: 100%; 50 | padding: 9px 0 9px 0; 51 | text-align: center; 52 | font-size: 75%; 53 | } 54 | 55 | div.footer a { 56 | color: #8A0808; 57 | text-decoration: underline; 58 | } 59 | 60 | div.related { 61 | background-color: #666666; 62 | line-height: 30px; 63 | color: #ffffff; 64 | } 65 | 66 | div.related a { 67 | color: #ffffff; 68 | } 69 | 70 | div.sphinxsidebar { 71 | float: right; 72 | } 73 | 74 | div.sphinxsidebar h3 { 75 | font-family: 'Trebuchet MS', sans-serif; 76 | color: #8A0808; 77 | font-size: 1.4em; 78 | font-weight: normal; 79 | margin: 0; 80 | padding: 0; 81 | } 82 | 83 | div.sphinxsidebar h3 a { 84 | color: #8A0808; 85 | } 86 | 87 | div.sphinxsidebar h4 { 88 | font-family: 'Trebuchet MS', sans-serif; 89 | color: #8A0808; 90 | font-size: 1.3em; 91 | font-weight: normal; 92 | margin: 5px 0 0 0; 93 | padding: 0; 94 | } 95 | 96 | div.sphinxsidebar p { 97 | color: #8A0808; 98 | } 99 | 100 | div.sphinxsidebar p.topless { 101 | margin: 5px 10px 10px 10px; 102 | } 103 | 104 | div.sphinxsidebar ul { 105 | margin: 10px; 106 | padding: 0; 107 | color: #8A0808; 108 | } 109 | 110 | div.sphinxsidebar a { 111 | color: #8A0808; 112 | } 113 | 114 | div.sphinxsidebar input { 115 | border: 1px solid #8A0808; 116 | font-family: sans-serif; 117 | font-size: 1em; 118 | } 119 | 120 | 121 | /* for collapsible sidebar */ 122 | div#sidebarbutton { 123 | background-color: #f2f2f2; 124 | } 125 | 126 | 127 | /* -- hyperlink styles ------------------------------------------------------ */ 128 | 129 | a { 130 | color: #8A0808; 131 | text-decoration: none; 132 | } 133 | 134 | a:visited { 135 | color: #8A0808; 136 | text-decoration: none; 137 | } 138 | 139 | a:hover { 140 | text-decoration: underline; 141 | } 142 | 143 | 144 | 145 | /* -- body styles ----------------------------------------------------------- */ 146 | 147 | div.body h1, 148 | div.body h2, 149 | div.body h3, 150 | div.body h4, 151 | div.body h5, 152 | div.body h6 { 153 | font-family: 'Trebuchet MS', sans-serif; 154 | background-color: #f2f2f2; 155 | font-weight: normal; 156 | color: #8A0808; 157 | border-bottom: 1px solid #ccc; 158 | margin: 20px -20px 10px -20px; 159 | padding: 3px 0 3px 10px; 160 | } 161 | 162 | div.body h1 { margin-top: 0; font-size: 200%; } 163 | div.body h2 { font-size: 160%; } 164 | div.body h3 { font-size: 140%; } 165 | div.body h4 { font-size: 120%; } 166 | div.body h5 { font-size: 110%; } 167 | div.body h6 { font-size: 100%; } 168 | 169 | a.headerlink { 170 | color: #8A0808; 171 | font-size: 0.8em; 172 | padding: 0 4px 0 4px; 173 | text-decoration: none; 174 | } 175 | 176 | a.headerlink:hover { 177 | background-color: #8A0808; 178 | color: white; 179 | } 180 | 181 | div.body p, div.body dd, div.body li { 182 | text-align: justify; 183 | line-height: 130%; 184 | } 185 | 186 | div.admonition p.admonition-title + p { 187 | display: inline; 188 | } 189 | 190 | div.admonition p { 191 | margin-bottom: 5px; 192 | } 193 | 194 | div.admonition pre { 195 | margin-bottom: 5px; 196 | } 197 | 198 | div.admonition ul, div.admonition ol { 199 | margin-bottom: 5px; 200 | } 201 | 202 | div.note { 203 | background-color: #eee; 204 | border: 1px solid #ccc; 205 | } 206 | 207 | div.seealso { 208 | background-color: #ffc; 209 | border: 1px solid #ff6; 210 | } 211 | 212 | div.topic { 213 | background-color: #eee; 214 | } 215 | 216 | div.warning { 217 | background-color: #ffe4e4; 218 | border: 1px solid #f66; 219 | } 220 | 221 | p.admonition-title { 222 | display: inline; 223 | } 224 | 225 | p.admonition-title:after { 226 | content: ":"; 227 | } 228 | 229 | pre { 230 | padding: 5px; 231 | background-color: #f2f2f2; 232 | color: #333333; 233 | line-height: 120%; 234 | border: 1px solid #ac9; 235 | border-left: none; 236 | border-right: none; 237 | } 238 | 239 | tt { 240 | background-color: #ecf0f3; 241 | padding: 0 1px 0 1px; 242 | font-size: 0.95em; 243 | } 244 | 245 | th { 246 | background-color: #ede; 247 | } 248 | 249 | .warning tt { 250 | background: #efc2c2; 251 | } 252 | 253 | .note tt { 254 | background: #d6d6d6; 255 | } 256 | 257 | .viewcode-back { 258 | font-family: sans-serif; 259 | } 260 | 261 | div.viewcode-block:target { 262 | background-color: #f4debf; 263 | border-top: 1px solid #ac9; 264 | border-bottom: 1px solid #ac9; 265 | } -------------------------------------------------------------------------------- /doc/pub/sphinx-cbc/_static/down-pressed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hplgit/web4sciapps/8d225ced1928e0706c43044429325c8ff9b01e76/doc/pub/sphinx-cbc/_static/down-pressed.png -------------------------------------------------------------------------------- /doc/pub/sphinx-cbc/_static/down.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hplgit/web4sciapps/8d225ced1928e0706c43044429325c8ff9b01e76/doc/pub/sphinx-cbc/_static/down.png -------------------------------------------------------------------------------- /doc/pub/sphinx-cbc/_static/file.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hplgit/web4sciapps/8d225ced1928e0706c43044429325c8ff9b01e76/doc/pub/sphinx-cbc/_static/file.png -------------------------------------------------------------------------------- /doc/pub/sphinx-cbc/_static/minus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hplgit/web4sciapps/8d225ced1928e0706c43044429325c8ff9b01e76/doc/pub/sphinx-cbc/_static/minus.png -------------------------------------------------------------------------------- /doc/pub/sphinx-cbc/_static/plus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hplgit/web4sciapps/8d225ced1928e0706c43044429325c8ff9b01e76/doc/pub/sphinx-cbc/_static/plus.png -------------------------------------------------------------------------------- /doc/pub/sphinx-cbc/_static/pygments.css: -------------------------------------------------------------------------------- 1 | .highlight .hll { background-color: #ffffcc } 2 | .highlight { background: #f0f0f0; } 3 | .highlight .c { color: #60a0b0; font-style: italic } /* Comment */ 4 | .highlight .err { border: 1px solid #FF0000 } /* Error */ 5 | .highlight .k { color: #007020; font-weight: bold } /* Keyword */ 6 | .highlight .o { color: #666666 } /* Operator */ 7 | .highlight .cm { color: #60a0b0; font-style: italic } /* Comment.Multiline */ 8 | .highlight .cp { color: #007020 } /* Comment.Preproc */ 9 | .highlight .c1 { color: #60a0b0; font-style: italic } /* Comment.Single */ 10 | .highlight .cs { color: #60a0b0; background-color: #fff0f0 } /* Comment.Special */ 11 | .highlight .gd { color: #A00000 } /* Generic.Deleted */ 12 | .highlight .ge { font-style: italic } /* Generic.Emph */ 13 | .highlight .gr { color: #FF0000 } /* Generic.Error */ 14 | .highlight .gh { color: #000080; font-weight: bold } /* Generic.Heading */ 15 | .highlight .gi { color: #00A000 } /* Generic.Inserted */ 16 | .highlight .go { color: #888888 } /* Generic.Output */ 17 | .highlight .gp { color: #c65d09; font-weight: bold } /* Generic.Prompt */ 18 | .highlight .gs { font-weight: bold } /* Generic.Strong */ 19 | .highlight .gu { color: #800080; font-weight: bold } /* Generic.Subheading */ 20 | .highlight .gt { color: #0044DD } /* Generic.Traceback */ 21 | .highlight .kc { color: #007020; font-weight: bold } /* Keyword.Constant */ 22 | .highlight .kd { color: #007020; font-weight: bold } /* Keyword.Declaration */ 23 | .highlight .kn { color: #007020; font-weight: bold } /* Keyword.Namespace */ 24 | .highlight .kp { color: #007020 } /* Keyword.Pseudo */ 25 | .highlight .kr { color: #007020; font-weight: bold } /* Keyword.Reserved */ 26 | .highlight .kt { color: #902000 } /* Keyword.Type */ 27 | .highlight .m { color: #40a070 } /* Literal.Number */ 28 | .highlight .s { color: #4070a0 } /* Literal.String */ 29 | .highlight .na { color: #4070a0 } /* Name.Attribute */ 30 | .highlight .nb { color: #007020 } /* Name.Builtin */ 31 | .highlight .nc { color: #0e84b5; font-weight: bold } /* Name.Class */ 32 | .highlight .no { color: #60add5 } /* Name.Constant */ 33 | .highlight .nd { color: #555555; font-weight: bold } /* Name.Decorator */ 34 | .highlight .ni { color: #d55537; font-weight: bold } /* Name.Entity */ 35 | .highlight .ne { color: #007020 } /* Name.Exception */ 36 | .highlight .nf { color: #06287e } /* Name.Function */ 37 | .highlight .nl { color: #002070; font-weight: bold } /* Name.Label */ 38 | .highlight .nn { color: #0e84b5; font-weight: bold } /* Name.Namespace */ 39 | .highlight .nt { color: #062873; font-weight: bold } /* Name.Tag */ 40 | .highlight .nv { color: #bb60d5 } /* Name.Variable */ 41 | .highlight .ow { color: #007020; font-weight: bold } /* Operator.Word */ 42 | .highlight .w { color: #bbbbbb } /* Text.Whitespace */ 43 | .highlight .mb { color: #40a070 } /* Literal.Number.Bin */ 44 | .highlight .mf { color: #40a070 } /* Literal.Number.Float */ 45 | .highlight .mh { color: #40a070 } /* Literal.Number.Hex */ 46 | .highlight .mi { color: #40a070 } /* Literal.Number.Integer */ 47 | .highlight .mo { color: #40a070 } /* Literal.Number.Oct */ 48 | .highlight .sb { color: #4070a0 } /* Literal.String.Backtick */ 49 | .highlight .sc { color: #4070a0 } /* Literal.String.Char */ 50 | .highlight .sd { color: #4070a0; font-style: italic } /* Literal.String.Doc */ 51 | .highlight .s2 { color: #4070a0 } /* Literal.String.Double */ 52 | .highlight .se { color: #4070a0; font-weight: bold } /* Literal.String.Escape */ 53 | .highlight .sh { color: #4070a0 } /* Literal.String.Heredoc */ 54 | .highlight .si { color: #70a0d0; font-style: italic } /* Literal.String.Interpol */ 55 | .highlight .sx { color: #c65d09 } /* Literal.String.Other */ 56 | .highlight .sr { color: #235388 } /* Literal.String.Regex */ 57 | .highlight .s1 { color: #4070a0 } /* Literal.String.Single */ 58 | .highlight .ss { color: #517918 } /* Literal.String.Symbol */ 59 | .highlight .bp { color: #007020 } /* Name.Builtin.Pseudo */ 60 | .highlight .vc { color: #bb60d5 } /* Name.Variable.Class */ 61 | .highlight .vg { color: #bb60d5 } /* Name.Variable.Global */ 62 | .highlight .vi { color: #bb60d5 } /* Name.Variable.Instance */ 63 | .highlight .il { color: #40a070 } /* Literal.Number.Integer.Long */ -------------------------------------------------------------------------------- /doc/pub/sphinx-cbc/_static/sidebar.js: -------------------------------------------------------------------------------- 1 | /* 2 | * sidebar.js 3 | * ~~~~~~~~~~ 4 | * 5 | * This script makes the Sphinx sidebar collapsible. 6 | * 7 | * .sphinxsidebar contains .sphinxsidebarwrapper. This script adds 8 | * in .sphixsidebar, after .sphinxsidebarwrapper, the #sidebarbutton 9 | * used to collapse and expand the sidebar. 10 | * 11 | * When the sidebar is collapsed the .sphinxsidebarwrapper is hidden 12 | * and the width of the sidebar and the margin-left of the document 13 | * are decreased. When the sidebar is expanded the opposite happens. 14 | * This script saves a per-browser/per-session cookie used to 15 | * remember the position of the sidebar among the pages. 16 | * Once the browser is closed the cookie is deleted and the position 17 | * reset to the default (expanded). 18 | * 19 | * :copyright: Copyright 2007-2011 by the Sphinx team, see AUTHORS. 20 | * :license: BSD, see LICENSE for details. 21 | * 22 | */ 23 | 24 | $(function() { 25 | // global elements used by the functions. 26 | // the 'sidebarbutton' element is defined as global after its 27 | // creation, in the add_sidebar_button function 28 | var bodywrapper = $('.bodywrapper'); 29 | var sidebar = $('.sphinxsidebar'); 30 | var sidebarwrapper = $('.sphinxsidebarwrapper'); 31 | 32 | // for some reason, the document has no sidebar; do not run into errors 33 | if (!sidebar.length) return; 34 | 35 | // original margin-left of the bodywrapper and width of the sidebar 36 | // with the sidebar expanded 37 | var bw_margin_expanded = bodywrapper.css('margin-left'); 38 | var ssb_width_expanded = sidebar.width(); 39 | 40 | // margin-left of the bodywrapper and width of the sidebar 41 | // with the sidebar collapsed 42 | var bw_margin_collapsed = '.8em'; 43 | var ssb_width_collapsed = '.8em'; 44 | 45 | // colors used by the current theme 46 | var dark_color = $('.related').css('background-color'); 47 | var light_color = $('.document').css('background-color'); 48 | 49 | function sidebar_is_collapsed() { 50 | return sidebarwrapper.is(':not(:visible)'); 51 | } 52 | 53 | function toggle_sidebar() { 54 | if (sidebar_is_collapsed()) 55 | expand_sidebar(); 56 | else 57 | collapse_sidebar(); 58 | } 59 | 60 | function collapse_sidebar() { 61 | sidebarwrapper.hide(); 62 | sidebar.css('width', ssb_width_collapsed); 63 | bodywrapper.css('margin-left', bw_margin_collapsed); 64 | sidebarbutton.css({ 65 | 'margin-left': '0', 66 | 'height': bodywrapper.height() 67 | }); 68 | sidebarbutton.find('span').text('»'); 69 | sidebarbutton.attr('title', _('Expand sidebar')); 70 | document.cookie = 'sidebar=collapsed'; 71 | } 72 | 73 | function expand_sidebar() { 74 | bodywrapper.css('margin-left', bw_margin_expanded); 75 | sidebar.css('width', ssb_width_expanded); 76 | sidebarwrapper.show(); 77 | sidebarbutton.css({ 78 | 'margin-left': ssb_width_expanded-12, 79 | 'height': bodywrapper.height() 80 | }); 81 | sidebarbutton.find('span').text('«'); 82 | sidebarbutton.attr('title', _('Collapse sidebar')); 83 | document.cookie = 'sidebar=expanded'; 84 | } 85 | 86 | function add_sidebar_button() { 87 | sidebarwrapper.css({ 88 | 'float': 'left', 89 | 'margin-right': '0', 90 | 'width': ssb_width_expanded - 28 91 | }); 92 | // create the button 93 | sidebar.append( 94 | '
«
' 95 | ); 96 | var sidebarbutton = $('#sidebarbutton'); 97 | light_color = sidebarbutton.css('background-color'); 98 | // find the height of the viewport to center the '<<' in the page 99 | var viewport_height; 100 | if (window.innerHeight) 101 | viewport_height = window.innerHeight; 102 | else 103 | viewport_height = $(window).height(); 104 | sidebarbutton.find('span').css({ 105 | 'display': 'block', 106 | 'margin-top': (viewport_height - sidebar.position().top - 20) / 2 107 | }); 108 | 109 | sidebarbutton.click(toggle_sidebar); 110 | sidebarbutton.attr('title', _('Collapse sidebar')); 111 | sidebarbutton.css({ 112 | 'color': '#FFFFFF', 113 | 'border-left': '1px solid ' + dark_color, 114 | 'font-size': '1.2em', 115 | 'cursor': 'pointer', 116 | 'height': bodywrapper.height(), 117 | 'padding-top': '1px', 118 | 'margin-left': ssb_width_expanded - 12 119 | }); 120 | 121 | sidebarbutton.hover( 122 | function () { 123 | $(this).css('background-color', dark_color); 124 | }, 125 | function () { 126 | $(this).css('background-color', light_color); 127 | } 128 | ); 129 | } 130 | 131 | function set_position_from_cookie() { 132 | if (!document.cookie) 133 | return; 134 | var items = document.cookie.split(';'); 135 | for(var k=0; k 4 | 5 | 6 | 7 | 8 | 9 | 10 | Search 11 | 12 | 13 | 14 | 15 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 45 | 46 | 47 | 48 | 49 | 52 | 53 | 54 | 55 | 56 | 57 | 63 | 64 | 65 | 66 |
75 | 76 |
77 |
78 |
79 |
80 | 81 |

Search

82 |
83 | 84 |

85 | Please activate JavaScript to enable the search 86 | functionality. 87 |

88 |
89 |

90 | From here you can search these documents. Enter your search 91 | words into the box below and click "search". Note that the search 92 | function will automatically search for all of the words. Pages 93 | containing fewer words won't appear in the result list. 94 |

95 |
96 | 97 | 98 | 99 |
100 | 101 |
102 | 103 |
104 | 105 |
106 |
107 |
108 | 117 |
118 |
119 | 128 |
129 | 135 |
136 | 137 | 138 | -------------------------------------------------------------------------------- /doc/pub/web4sa.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hplgit/web4sciapps/8d225ced1928e0706c43044429325c8ff9b01e76/doc/pub/web4sa.pdf -------------------------------------------------------------------------------- /doc/src/web4sa/clean.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | name=web4sa 3 | doconce clean 4 | rm -rf ${name}_*.html sphinx-* automake_sphinx.py 5 | rm -rf src-${name}/apps/vib/vib1_flask/static/*.png 6 | rm -rf src-${name}/apps/vib/vib3_flask/static 7 | rm -rf src-${name}/apps/vib/vib1_django/static 8 | rm -rf src-${name}/apps/vib/vib2_django/static 9 | -------------------------------------------------------------------------------- /doc/src/web4sa/exer/Taylor_approx/compute.py: -------------------------------------------------------------------------------- 1 | 2 | def formula2series2pyfunc(formula, N, x, x0=0): 3 | """ 4 | Convert a sympy expression formula in some independent 5 | variable x to a series representation of degree N terms 6 | and create a Python function for evaluating this series 7 | representation. Return Python functions for the formula 8 | and the series expansion, plus a LaTeX formula for the 9 | series expansion. 10 | """ 11 | import sympy as sp 12 | series = formula.series(x, x0, N+1).removeO() 13 | series_pyfunc = sp.lambdify([x], series, modules='numpy') 14 | formula_pyfunc = sp.lambdify([x], formula, modules='numpy') 15 | # Return latex code with O() term since it starts with the lowest 16 | # order term and therefore looks better 17 | return formula_pyfunc, series_pyfunc, sp.latex(formula.series(x, x0, N+1)) 18 | 19 | legends = [] # Store previous legends if not erase 20 | 21 | def visualize_series( 22 | formula, # string: formula 23 | independent_variable, # string: name of independent variable 24 | N, # int: degree of polynomial approximation 25 | xmin, xmax, ymin, ymax, # strings: extent of axes 26 | legend_loc, # string: upper left, etc. 27 | x0='0', # string: point of expansion 28 | erase='yes', # string: 'yes' or 'no' 29 | ): 30 | # Turn independent variable into sympy symbol, stored in x 31 | import sympy as sp 32 | exec('x = %s = sp.symbols("%s")' % 33 | (independent_variable, independent_variable)) 34 | # Turn string formula into sympy expression. Need to 35 | # evaluate formula in the sympy namespace plus the 36 | # independent variable. 37 | namespace = sp.__dict__.copy() 38 | local = {} 39 | local[independent_variable] = x 40 | namespace.update(local) 41 | formula = eval(formula, namespace) 42 | # Turn x0 into sympy expression 43 | x0 = eval(x0, sp.__dict__) 44 | f, s, latex = formula2series2pyfunc(formula, N=N, x=x) 45 | # Make plot 46 | import numpy as np 47 | # Assume xmin, xmax, ymin, ymax are all strings and 48 | # allow symbols like pi 49 | xmin = eval(xmin, np.__dict__) 50 | xmax = eval(xmax, np.__dict__) 51 | ymin = eval(ymin, np.__dict__) 52 | ymax = eval(ymax, np.__dict__) 53 | x = np.linspace(xmin, xmax, 1001) 54 | import matplotlib.pyplot as plt 55 | global legends 56 | if erase == 'yes': # Start new figure? 57 | plt.figure() 58 | legends = [] 59 | if not legends: 60 | # We come here every time the figure is empty so 61 | # we need to draw the formula 62 | legends.append('$%s$' % sp.latex(formula)) 63 | plt.plot(x, f(x)) 64 | plt.plot(x, s(x)) 65 | plt.xlabel(independent_variable) 66 | plt.axis([xmin, xmax, ymin, ymax]) 67 | legends.append('series, N=%d' % N) 68 | plt.legend(legends, loc=legend_loc) 69 | from StringIO import StringIO 70 | figfile = StringIO() 71 | plt.savefig(figfile, format='png') 72 | figfile.seek(0) # rewind to beginning of file 73 | import base64 74 | figdata_png = base64.b64encode(figfile.buf) 75 | return figdata_png, latex 76 | 77 | if __name__ == '__main__': 78 | visualize_series( 79 | 'sin(t)', 't', N=12, 80 | xmin='0', xmax='2*pi', ymin='-2', ymax='2', 81 | x0='0') 82 | -------------------------------------------------------------------------------- /doc/src/web4sa/exer/Taylor_approx/controller.py: -------------------------------------------------------------------------------- 1 | from model import InputForm 2 | from flask import Flask, render_template, request 3 | from compute import visualize_series as compute 4 | 5 | app = Flask(__name__) 6 | 7 | @app.route('/Taylor', methods=['GET', 'POST']) 8 | def index(): 9 | form = InputForm(request.form) 10 | if request.method == 'POST' and form.validate(): 11 | result = compute(formula=form.Formula.data, 12 | independent_variable=form.Variable.data, 13 | N=form.N.data, 14 | xmin=form.xmin.data, 15 | xmax=form.xmax.data, 16 | ymin=form.ymin.data, 17 | ymax=form.ymax.data, 18 | legend_loc=form.legend_loc.data, 19 | x0=form.x0.data, 20 | erase=form.Erase.data) 21 | else: 22 | result = None 23 | print request.method, [field.errors for field in form] 24 | 25 | return render_template('view.html', form=form, result=result) 26 | 27 | if __name__ == '__main__': 28 | app.run(debug=True) 29 | -------------------------------------------------------------------------------- /doc/src/web4sa/exer/Taylor_approx/model.py: -------------------------------------------------------------------------------- 1 | from wtforms import Form, TextField, SelectField, IntegerField, validators 2 | from math import pi 3 | 4 | class InputForm(Form): 5 | Variable = TextField( 6 | label='Name of independent variable', 7 | default='x', 8 | validators=[validators.InputRequired()]) 9 | Formula = TextField( 10 | label='Expression in independent variable', 11 | default='sin(x)', 12 | validators=[validators.InputRequired()]) 13 | xmin = TextField( 14 | label='Minimum x value in the plot', default='0', 15 | validators=[validators.InputRequired()]) 16 | xmax = TextField( 17 | label='Maximum x value in the plot', default='2*pi', 18 | validators=[validators.InputRequired()]) 19 | ymin = TextField( 20 | label='Minimum y value in the plot', default='-2', 21 | validators=[validators.InputRequired()]) 22 | ymax = TextField( 23 | label='Maximum y value in the plot', default='2', 24 | validators=[validators.InputRequired()]) 25 | x0 = TextField( 26 | label='Point for series expansion', default='0', 27 | validators=[validators.InputRequired()]) 28 | N = IntegerField( 29 | label='Polynomial degree of series approximation', default=7, 30 | validators=[validators.InputRequired()]) 31 | legend_loc = TextField( 32 | label='Location of legend in the plot', default='lower left', 33 | validators=[validators.InputRequired()]) 34 | Erase = SelectField( 35 | label='Erase all curves?', 36 | # choices is (value, label) pairs: label gets printed 37 | # value is form.Erase.data 38 | choices=[('yes', 'Yes'), ('no', 'No')], default=2) 39 | -------------------------------------------------------------------------------- /doc/src/web4sa/exer/Taylor_approx/templates/view.html: -------------------------------------------------------------------------------- 1 | 9 | 12 | 13 | 14 | 37 | 38 | {% if result != None %} 39 | 50 | {% endif %} 51 | 52 |
15 |
16 | 17 | {% for field in form %} 18 | 19 | 20 | {% if field.name != 'Erase' %} 21 | 22 | {% else %} 23 | 24 | 25 | {% endif %} 26 | {% if field.errors %} 27 | 31 | {% endif %} 32 | 33 | {% endfor %} 34 |
{{ field.label }}{{ field(size=12) }}{{ field }}
    28 | {% for error in field.errors %} 29 |
  • {{ error }}
  • 30 | {% endfor %}
35 |

36 |
40 |

41 | 42 |

43 |

44 |

45 | Series expansion of the formula: 46 | $$ {{ result[1] }} $$ 47 |
48 |

49 |
53 | -------------------------------------------------------------------------------- /doc/src/web4sa/exer/addmul/compute.py: -------------------------------------------------------------------------------- 1 | def add(a, b): 2 | return a + b 3 | 4 | def mul(p, q): 5 | return p*q 6 | 7 | if __name__ == '__main__': 8 | print add(1, 2), mul(3, 4) 9 | -------------------------------------------------------------------------------- /doc/src/web4sa/exer/addmul/controller.py: -------------------------------------------------------------------------------- 1 | from model import AddForm, MulForm 2 | from flask import Flask, render_template, request 3 | from compute import add, mul 4 | 5 | app = Flask(__name__) 6 | 7 | @app.route('/addmul', methods=['GET', 'POST']) 8 | def index(): 9 | form = {} 10 | result = {} 11 | 12 | # Try to make as common code as possible for the two apps 13 | name = 'add' 14 | f = form[name] = AddForm(request.form) 15 | if request.method == 'POST' and f.validate() and \ 16 | request.form['btn'] == 'Add': 17 | result[name] = add(f.a.data, f.b.data) 18 | else: 19 | result[name] = None 20 | 21 | name = 'mul' 22 | f = form[name] = MulForm(request.form) 23 | if request.method == 'POST' and f.validate() and \ 24 | request.form['btn'] == 'Multiply': 25 | result[name] = mul(f.p.data, f.q.data) 26 | else: 27 | result[name] = None 28 | 29 | return render_template('view.html', 30 | form=form, result=result) 31 | 32 | if __name__ == '__main__': 33 | app.run(debug=True) 34 | -------------------------------------------------------------------------------- /doc/src/web4sa/exer/addmul/model.py: -------------------------------------------------------------------------------- 1 | from wtforms import Form, FloatField 2 | 3 | class AddForm(Form): 4 | a = FloatField(label='', default=1.0) 5 | b = FloatField(label='', default=1.0) 6 | 7 | class MulForm(Form): 8 | p = FloatField(label='', default=2) 9 | q = FloatField(label='', default=2) 10 | -------------------------------------------------------------------------------- /doc/src/web4sa/exer/gen_ext/compute.py: -------------------------------------------------------------------------------- 1 | from numpy import exp, cos, linspace, zeros_like 2 | import matplotlib.pyplot as plt 3 | import os, time, glob, math 4 | 5 | def damped_vibrations(t, A, b, w): 6 | return A*exp(-b*t)*cos(w*t) 7 | 8 | def compute_vib(A=1, b=0.2, w=2*math.pi, T=5, resolution=500): 9 | """Return filename of plot of the damped_vibration function.""" 10 | t = linspace(0, T, resolution+1) 11 | y = damped_vibrations(t, A, b, w) 12 | plt.figure() # needed to avoid adding curves in plot 13 | plt.plot(t, y) 14 | plt.title('A=%g, b=%g, w=%g' % (A, b, w)) 15 | if not os.path.isdir('static'): 16 | os.mkdir('static') 17 | else: 18 | # Remove old plot files 19 | for filename in glob.glob(os.path.join('static', '*.png')): 20 | os.remove(filename) 21 | # Use time since Jan 1, 1970 in filename in order make 22 | # a unique filename that the browser has not chached 23 | plotfile = os.path.join('static', str(time.time()) + '.png') 24 | plt.savefig(plotfile) 25 | return plotfile 26 | 27 | def gamma_density(x, a, h, A): 28 | # http://en.wikipedia.org/wiki/Gamma_distribution 29 | xA = x/float(A) 30 | return abs(h)/(math.gamma(a)*A)*(xA)**(a*h-1)*exp(-xA**h) 31 | 32 | def gamma_cumulative(x, a, h, A): 33 | # Integrate gamma_density using the Trapezoidal rule. 34 | # Assume x is array. 35 | g = gamma_density(x, a, h, A) 36 | r = zeros_like(x) 37 | for i in range(len(r)-1): 38 | r[i+1] = r[i] + 0.5*(g[i] + g[i+1])*(x[i+1] - x[i]) 39 | return r 40 | 41 | def compute_gamma(a=0.5, h=2.0, A=math.sqrt(2), resolution=500, 42 | range=[0,7]): 43 | """Return plot and mean/st.dev. value of the gamma density.""" 44 | print 'range:', type(range), range 45 | gah = math.gamma(a + 1./h) 46 | mean = A*gah/math.gamma(a) 47 | stdev = A/math.gamma(a)*math.sqrt( 48 | math.gamma(a + 2./h)*math.gamma(a) - gah**2) 49 | x = linspace(0, range[1]*stdev, resolution+1) 50 | y = gamma_density(x, a, h, A) 51 | plt.figure() # needed to avoid adding curves in plot 52 | plt.plot(x, y) 53 | plt.title('a=%g, h=%g, A=%g' % (a, h, A)) 54 | if not os.path.isdir('static'): 55 | os.mkdir('static') 56 | else: 57 | # Remove old plot files 58 | for filename in glob.glob(os.path.join('static', '*.png')): 59 | os.remove(filename) 60 | # Use time since Jan 1, 1970 in filename in order make 61 | # a unique filename that the browser has not chached 62 | t = str(time.time()) 63 | plotfile1 = os.path.join('static', 'density_%s.png' % t) 64 | plotfile2 = os.path.join('static', 'cumulative_%s.png' % t) 65 | plt.savefig(plotfile1) 66 | y = gamma_cumulative(x, a, h, A) 67 | plt.figure() 68 | plt.plot(x, y) 69 | plt.grid(True) 70 | plt.savefig(plotfile2) 71 | return plotfile1, plotfile2, mean, stdev 72 | 73 | if __name__ == '__main__': 74 | print compute_vib() 75 | -------------------------------------------------------------------------------- /doc/src/web4sa/exer/gen_ext/controller.py: -------------------------------------------------------------------------------- 1 | from view import app 2 | 3 | if __name__ == '__main__': 4 | app.run(debug=True) 5 | -------------------------------------------------------------------------------- /doc/src/web4sa/exer/gen_ext/model.py: -------------------------------------------------------------------------------- 1 | """ 2 | Example on generic model.py file which inspects the arguments 3 | of the compute function and automatically generates a relevant 4 | InputForm class. 5 | """ 6 | 7 | import wtforms 8 | from math import pi 9 | from compute import compute_gamma as compute 10 | import numpy as np 11 | import inspect 12 | arg_names = inspect.getargspec(compute).args 13 | defaults = inspect.getargspec(compute).defaults 14 | 15 | class InputForm(wtforms.Form): 16 | pass 17 | 18 | # Augment defaults with None elements for the positional 19 | # arguments 20 | defaults = [None]*(len(arg_names)-len(defaults)) + list(defaults) 21 | # Map type of default to right form field 22 | type2form = {type(1.0): wtforms.FloatField, 23 | type(1): wtforms.IntegerField, 24 | type(''): wtforms.TextField, 25 | type([]): wtforms.TextField, 26 | type(()): wtforms.TextField, 27 | type(np.array([1,2.])): wtforms.TextField, 28 | } 29 | 30 | def get_type_as_str(obj): 31 | return str(type(obj)).split("'")[1] 32 | 33 | for name, value in zip(arg_names, defaults): 34 | if value is None: 35 | setattr(InputForm, name, wtforms.FloatField( 36 | validators=[wtforms.validators.InputRequired()])) 37 | else: 38 | if type(value) in type2form: 39 | setattr(InputForm, name, type2form[type(value)]( 40 | default=value, 41 | label='(%s)' % get_type_as_str(value), 42 | validators=[wtforms.validators.InputRequired()])) 43 | else: 44 | raise TypeError('argument %s %s not supported' % 45 | name, type(value)) 46 | 47 | if __name__ == '__main__': 48 | for item in dir(InputForm): 49 | if item in arg_names: 50 | print item, getattr(InputForm, item) 51 | -------------------------------------------------------------------------------- /doc/src/web4sa/exer/gen_ext/templates/view.html: -------------------------------------------------------------------------------- 1 |
2 | 3 | {% for field in form %} 4 | 5 | 6 | 12 | {% endfor %} 13 |
{{ field.name }} {{ field }}{{ field.label }}{% if field.errors %} 7 |
    8 | {% for error in field.errors %} 9 |
  • {{ error }}
  • 10 | {% endfor %}
11 | {% endif %}
14 |

15 | 16 | {% if result != None %} 17 | {{ result|safe }} 18 | {% endif %} 19 | -------------------------------------------------------------------------------- /doc/src/web4sa/exer/gen_ext/templates/view_results.html: -------------------------------------------------------------------------------- 1 |

2 | 3 | 4 | 5 | 6 | 7 | 11 |
8 | Mean value: {{ result[2] }}
9 | Standard deviation value: {{ result[3] }} 10 |
12 |

13 | -------------------------------------------------------------------------------- /doc/src/web4sa/exer/gen_ext/templates/view_results_default.py: -------------------------------------------------------------------------------- 1 |

2 | {% if result != None %} 3 | {% if type(result) == type("") and 4 | result[:-4] == '.png' or result[:-4] == '.gif' or 5 | result[:-4] == '.jpg' %} 6 | 7 | {% else %} 8 | {{ str(result) }} 9 | {% endif %} 10 | {% endif %} 11 |

12 | -------------------------------------------------------------------------------- /doc/src/web4sa/exer/gen_ext/view.py: -------------------------------------------------------------------------------- 1 | from model import InputForm 2 | from flask import Flask, render_template, request 3 | from compute import compute_gamma as compute 4 | import sys, os, inspect 5 | 6 | app = Flask(__name__) 7 | 8 | @app.route('/vib3_ext', methods=['GET', 'POST']) 9 | def index(): 10 | form = InputForm(request.form) 11 | if request.method == 'POST' and form.validate(): 12 | arg_names = inspect.getargspec(compute).args 13 | kwargs = {name: getattr(form, name).data 14 | for name in arg_names if hasattr(form, name)} 15 | # Run eval on the text 16 | # Note that form.name.label is 17 | for name in kwargs: 18 | if hasattr(form, name) and \ 19 | hasattr(getattr(form, name), 'label'): 20 | label = str(getattr(form, name).label) 21 | for tp in ('(list)', '(tuple)', '(nd.array)'): 22 | if tp in label: 23 | kwargs[name] = eval(kwargs[name]) 24 | 25 | result = compute(**kwargs) 26 | else: 27 | result = None 28 | if result: 29 | # result must be transformed to HTML and inserted as a 30 | # string in the generic view.html file 31 | result = render_template('view_results.html', result=result) 32 | return render_template('view.html', form=form, result=result) 33 | -------------------------------------------------------------------------------- /doc/src/web4sa/exer/plot_formula/README.txt: -------------------------------------------------------------------------------- 1 | 1. Make the compute function. 2 | 2. Copy model.py and controller.py from vib1. 3 | 3. Edit *.py. 4 | -------------------------------------------------------------------------------- /doc/src/web4sa/exer/plot_formula/compute.py: -------------------------------------------------------------------------------- 1 | def plot_formula(formula, domain, erase): 2 | """ 3 | formula: string containing function expression of x to be plotted. 4 | domain: 2-list of min and mix x value in the plot. 5 | Return PNG plot as a string. 6 | """ 7 | # Evaluate domain is list and extract xmin and xmax. 8 | # Evaluate in numpy namespace so that '[0, pi/2]' is a 9 | # possible domain specification. 10 | import numpy as np 11 | input_error = False 12 | try: 13 | domain_list = eval(domain, np.__dict__) 14 | except Exception as e: 15 | input_error = True 16 | if not isinstance(domain, list) and len(domain) == 2: 17 | input_error = True 18 | if input_error: 19 | raise ValueError('Specified domain "%s" is not a 2-list' % domain) 20 | xmin, xmax = domain_list 21 | 22 | # Define x coordinates 23 | x = np.linspace(xmin, xmax, 10001) 24 | # Turn formula into numpy expression. 25 | # Need np.__dict__ namespace and the x defined here 26 | namespace = np.__dict__.copy() 27 | namespace.update({'x': x}) 28 | try: 29 | y = eval(formula, namespace) 30 | except Exception as e: 31 | raise ValueError( 32 | 'expression "%s" could not be evaluated:\n%s' % 33 | formula, str(e)) 34 | 35 | # Make plot 36 | import matplotlib.pyplot as plt 37 | if erase == 'yes': 38 | plt.figure() 39 | plt.plot(x, y) 40 | plt.xlabel('x') 41 | from StringIO import StringIO 42 | figfile = StringIO() 43 | plt.savefig(figfile, format='png') 44 | figfile.seek(0) # rewind to beginning of file 45 | import base64 46 | figdata_png = base64.b64encode(figfile.buf) 47 | return figdata_png 48 | -------------------------------------------------------------------------------- /doc/src/web4sa/exer/plot_formula/controller.py: -------------------------------------------------------------------------------- 1 | from model import InputForm 2 | from flask import Flask, render_template, request 3 | from compute import plot_formula as compute 4 | 5 | app = Flask(__name__) 6 | 7 | @app.route('/formula', methods=['GET', 'POST']) 8 | def index(): 9 | form = InputForm(request.form) 10 | if request.method == 'POST' and form.validate(): 11 | result = compute(form.Formula.data, form.Domain.data, 12 | form.Erase.data) 13 | else: 14 | result = None 15 | 16 | return render_template('view.html', form=form, result=result) 17 | 18 | if __name__ == '__main__': 19 | app.run(debug=True) 20 | -------------------------------------------------------------------------------- /doc/src/web4sa/exer/plot_formula/model.py: -------------------------------------------------------------------------------- 1 | from wtforms import Form, TextField, SelectField, validators 2 | from math import pi 3 | 4 | class InputForm(Form): 5 | Formula = TextField( 6 | label='Expression in x', 7 | default='sin(x)', 8 | validators=[validators.InputRequired()]) 9 | Domain = TextField( 10 | label='Domain: [xmin, xmax]', default='[0, 2*pi]', 11 | validators=[validators.InputRequired()]) 12 | Erase = SelectField( 13 | label='Erase all curves?', 14 | # choices is (value, label) pairs: label gets printed 15 | # value is form.Erase.data 16 | choices=[('yes', 'Yes'), ('no', 'No')], default=2) 17 | -------------------------------------------------------------------------------- /doc/src/web4sa/exer/plot_formula/templates/view.html: -------------------------------------------------------------------------------- 1 |
2 | 3 | {% for field in form %} 4 | 5 | 6 | {% if field.name != 'Erase' %} 7 | 8 | {% else %} 9 | 10 | 11 | {% endif %} 12 | {% if field.errors %} 13 | 17 | {% endif %} 18 | 19 | {% endfor %} 20 |
{{ field.label }}{{ field(size=12) }}{{ field }}
    14 | {% for error in field.errors %} 15 |
  • {{ error }}
  • 16 | {% endfor %}
21 |

22 | 23 | {% if result != None %} 24 |

25 | 26 |

27 | {% endif %} 28 | -------------------------------------------------------------------------------- /doc/src/web4sa/fig-web4sa/Taylor_approx.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hplgit/web4sciapps/8d225ced1928e0706c43044429325c8ff9b01e76/doc/src/web4sa/fig-web4sa/Taylor_approx.png -------------------------------------------------------------------------------- /doc/src/web4sa/fig-web4sa/Taylor_approx_exp2t.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hplgit/web4sciapps/8d225ced1928e0706c43044429325c8ff9b01e76/doc/src/web4sa/fig-web4sa/Taylor_approx_exp2t.pdf -------------------------------------------------------------------------------- /doc/src/web4sa/fig-web4sa/Taylor_approx_exp2t.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hplgit/web4sciapps/8d225ced1928e0706c43044429325c8ff9b01e76/doc/src/web4sa/fig-web4sa/Taylor_approx_exp2t.png -------------------------------------------------------------------------------- /doc/src/web4sa/fig-web4sa/gen_flask_gamma.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hplgit/web4sciapps/8d225ced1928e0706c43044429325c8ff9b01e76/doc/src/web4sa/fig-web4sa/gen_flask_gamma.png -------------------------------------------------------------------------------- /doc/src/web4sa/fig-web4sa/hw1_django_input.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hplgit/web4sciapps/8d225ced1928e0706c43044429325c8ff9b01e76/doc/src/web4sa/fig-web4sa/hw1_django_input.png -------------------------------------------------------------------------------- /doc/src/web4sa/fig-web4sa/hw1_django_output.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hplgit/web4sciapps/8d225ced1928e0706c43044429325c8ff9b01e76/doc/src/web4sa/fig-web4sa/hw1_django_output.png -------------------------------------------------------------------------------- /doc/src/web4sa/fig-web4sa/hw1_flask_input.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hplgit/web4sciapps/8d225ced1928e0706c43044429325c8ff9b01e76/doc/src/web4sa/fig-web4sa/hw1_flask_input.png -------------------------------------------------------------------------------- /doc/src/web4sa/fig-web4sa/hw1_flask_output.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hplgit/web4sciapps/8d225ced1928e0706c43044429325c8ff9b01e76/doc/src/web4sa/fig-web4sa/hw1_flask_output.png -------------------------------------------------------------------------------- /doc/src/web4sa/fig-web4sa/hw2_django_output.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hplgit/web4sciapps/8d225ced1928e0706c43044429325c8ff9b01e76/doc/src/web4sa/fig-web4sa/hw2_django_output.png -------------------------------------------------------------------------------- /doc/src/web4sa/fig-web4sa/hw2_flask_output.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hplgit/web4sciapps/8d225ced1928e0706c43044429325c8ff9b01e76/doc/src/web4sa/fig-web4sa/hw2_flask_output.png -------------------------------------------------------------------------------- /doc/src/web4sa/fig-web4sa/login_main.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hplgit/web4sciapps/8d225ced1928e0706c43044429325c8ff9b01e76/doc/src/web4sa/fig-web4sa/login_main.png -------------------------------------------------------------------------------- /doc/src/web4sa/fig-web4sa/login_register.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hplgit/web4sciapps/8d225ced1928e0706c43044429325c8ff9b01e76/doc/src/web4sa/fig-web4sa/login_register.png -------------------------------------------------------------------------------- /doc/src/web4sa/fig-web4sa/plot_formula.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hplgit/web4sciapps/8d225ced1928e0706c43044429325c8ff9b01e76/doc/src/web4sa/fig-web4sa/plot_formula.png -------------------------------------------------------------------------------- /doc/src/web4sa/fig-web4sa/upload1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hplgit/web4sciapps/8d225ced1928e0706c43044429325c8ff9b01e76/doc/src/web4sa/fig-web4sa/upload1.png -------------------------------------------------------------------------------- /doc/src/web4sa/fig-web4sa/upload2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hplgit/web4sciapps/8d225ced1928e0706c43044429325c8ff9b01e76/doc/src/web4sa/fig-web4sa/upload2.png -------------------------------------------------------------------------------- /doc/src/web4sa/fig-web4sa/upload3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hplgit/web4sciapps/8d225ced1928e0706c43044429325c8ff9b01e76/doc/src/web4sa/fig-web4sa/upload3.png -------------------------------------------------------------------------------- /doc/src/web4sa/fig-web4sa/vib1_flask_bootstrap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hplgit/web4sciapps/8d225ced1928e0706c43044429325c8ff9b01e76/doc/src/web4sa/fig-web4sa/vib1_flask_bootstrap.png -------------------------------------------------------------------------------- /doc/src/web4sa/fig-web4sa/vib1_flask_bootswatch_journal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hplgit/web4sciapps/8d225ced1928e0706c43044429325c8ff9b01e76/doc/src/web4sa/fig-web4sa/vib1_flask_bootswatch_journal.png -------------------------------------------------------------------------------- /doc/src/web4sa/fig-web4sa/vib1_flask_error1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hplgit/web4sciapps/8d225ced1928e0706c43044429325c8ff9b01e76/doc/src/web4sa/fig-web4sa/vib1_flask_error1.png -------------------------------------------------------------------------------- /doc/src/web4sa/fig-web4sa/vib1_flask_input.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hplgit/web4sciapps/8d225ced1928e0706c43044429325c8ff9b01e76/doc/src/web4sa/fig-web4sa/vib1_flask_input.png -------------------------------------------------------------------------------- /doc/src/web4sa/fig-web4sa/vib1_flask_latex.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hplgit/web4sciapps/8d225ced1928e0706c43044429325c8ff9b01e76/doc/src/web4sa/fig-web4sa/vib1_flask_latex.png -------------------------------------------------------------------------------- /doc/src/web4sa/fig-web4sa/vib1_flask_output.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hplgit/web4sciapps/8d225ced1928e0706c43044429325c8ff9b01e76/doc/src/web4sa/fig-web4sa/vib1_flask_output.png -------------------------------------------------------------------------------- /doc/src/web4sa/fig-web4sa/vib1_flask_table2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hplgit/web4sciapps/8d225ced1928e0706c43044429325c8ff9b01e76/doc/src/web4sa/fig-web4sa/vib1_flask_table2.png -------------------------------------------------------------------------------- /doc/src/web4sa/fig-web4sa/vib2_flask_error1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hplgit/web4sciapps/8d225ced1928e0706c43044429325c8ff9b01e76/doc/src/web4sa/fig-web4sa/vib2_flask_error1.png -------------------------------------------------------------------------------- /doc/src/web4sa/html_templates/template_django.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 16 | 17 | 18 | 19 | %(title)s 20 | 21 |
22 |
23 | 26 |
27 | 32 |
33 |
34 |
35 | 36 | 37 |
38 | 45 | 46 |
47 | 48 | %(main)s 49 | 50 |
51 | 52 | 58 |
59 | 60 | 61 | -------------------------------------------------------------------------------- /doc/src/web4sa/html_templates/template_flask.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 16 | 17 | 18 | 19 | %(title)s 20 | 21 |
22 |
23 | 26 |
27 | 32 |
33 |
34 |
35 | 36 |
37 | 44 | 45 |
46 | 47 | %(main)s 48 | 49 |
50 | 51 | 57 |
58 | 59 | 60 | -------------------------------------------------------------------------------- /doc/src/web4sa/html_templates/template_flask_django.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 16 | 17 | 18 | 19 | %(title)s 20 | 21 |
22 |
23 | 26 |
27 | 33 |
34 |
35 |
36 | 37 |
38 | 45 | 46 |
47 | 48 | %(main)s 49 | 50 |
51 | 52 | 58 |
59 | 60 | 61 | -------------------------------------------------------------------------------- /doc/src/web4sa/index.do.txt: -------------------------------------------------------------------------------- 1 | TITLE: Using Web Frameworks for Scientific Applications 2 | AUTHOR: Hans Petter Langtangen at Center for Biomedical Computing, Simula Research Laboratory and Department of Informatics, University of Oslo 3 | AUTHOR: Anders Johansen at Center for Biomedical Computing, Simula Research Laboratory 4 | DATE: today 5 | 6 | <% 7 | name = 'web4sa' 8 | 9 | import glob 10 | sphinx_styles = ', '.join(['"%s style": "%s/index.html"' % (n[7:], n) 11 | for n in glob.glob('sphinx-*') 12 | if n != 'sphinx-rootdir']) 13 | %> 14 | 15 | #======= Tutorials on web frameworks for scientific applications ======= 16 | 17 | * "Flask tutorial in HTML": "${name}_flask.html" 18 | * "Django tutorial in HTML": "${name}_django.html" 19 | * "Flask and Django tutorial in HTML": "${name}_solarized.html" 20 | * "Flask and Django tutorial in one big HTML file": "${name}_plain_all.html" 21 | * "Flask and Django tutorial in Sphinx": "sphinx-cbc/index.html" 22 | * "Flask and Django tutorial in LaTeX/PDF": "${name}.pdf" 23 | -------------------------------------------------------------------------------- /doc/src/web4sa/links.do.txt: -------------------------------------------------------------------------------- 1 | # #if TOPIC == 'Flask+Django' 2 | ======= Resources ======= 3 | # #else 4 | ======= ${TOPIC} resources ======= 5 | # #endif 6 | 7 | # #if TOPIC in ('Flask+Django', 'Flask') 8 | 9 | # #if TOPIC == 'Flask+Django' 10 | ===== Flask resources ===== 11 | # #endif 12 | 13 | * "Flask website": "http://flask.pocoo.org/" 14 | * "Flask Quick Start": "http://flask.pocoo.org/docs/0.10/tutorial/" 15 | * "Flask tutorial": "http://flask.pocoo.org/docs/0.10/tutorial/" 16 | * "The Flask Mega-Tutorial": "http://blog.miguelgrinberg.com/post/the-flask-mega-tutorial-part-i-hello-world" by M. Grinberg 17 | * "WTForms Documentation": "http://wtforms.simplecodes.com/docs/0.6/index.html" 18 | * "The Jinja2 templating language": "http://jinja.pocoo.org/docs/" 19 | * "The Werkzeug library": "http://werkzeug.pocoo.org/" 20 | * "An Introduction to Python's Flask Framework": "http://code.tutsplus.com/tutorials/an-introduction-to-pythons-flask-framework--net-28822" by L. Polepeddi 21 | * "Discover Flask, Part I - Setting up a Static Site": "https://realpython.com/blog/python/introduction-to-flask-part-1-setting-up-a-static-site/" 22 | * Flaskr: A Minimal Blog Application: "Code": "https://github.com/mitsuhiko/flask/tree/master/examples/flaskr/", "Explanation": "https://stormpath.com/blog/build-a-flask-app-in-30-minutes/" 23 | * "Flask Login with Facebook, Twitter, and OpenID": "http://peterhudec.github.io/authomatic/examples/flask-simple.html" 24 | * "Lightweight Python Apps with Flask, Bootstrap, and Heroku": "http://blog.shea.io/lightweight-python-apps-with-flask-twitter-bootstrap-and-heroku/" by R. Shea 25 | * "How to Structure Large Flask Applications": "https://www.digitalocean.com/community/tutorials/how-to-structure-large-flask-applications" 26 | * "Explore Flask": "https://exploreflask.com/index.html" by R. Picard (online book) 27 | * "Flask Mega Tutorial for Data Scientists": "http://www.datacommunitydc.org/blog/2014/02/flask-mega-meta-tutorial-data-scientists" 28 | * "Quick Flask++ tutorial": "http://maximebf.com/blog/2012/10/building-websites-in-python-with-flask/#.UxV4jHVdXn4" 29 | * "Flask-Bootstrap": "https://github.com/mbr/flask-bootstrap" with "documentation": "http://pythonhosted.org/Flask-Bootstrap/", "basic usage": "http://pythonhosted.org/Flask-Bootstrap/basic-usage.html" and "example": "https://github.com/mbr/flask-bootstrap/blob/master/sample_application/__init__.py" 30 | * "Skulpt: Interactive Python in the browser": "http://www.skulpt.org/" (but no support for `numpy`, `scipy`, or `matplotlib`) 31 | 32 | # #ifdef INTERESTING_BUT_NOT_RELEVANT 33 | * "A complete modern Python project with virtualenv, testing, setup.py, etc.": "https://github.com/splaice/py-bootstrap" 34 | * "Python for computer games": "http://inventwithpython.com/" 35 | * "Flask and Boostrap intro": "http://pythonthusiast.pythonblogs.com/230_pythonthusiast/archive/1309_building_in_openshift_part_iv__application_layout_and_templating_using_bootstrap_3_and_jinja_2.html" ("sample app": "http://bio-ekowibowo.rhcloud.com/" has sign in functionality and bootstrap layout explained "here": "http://pythonthusiast.pythonblogs.com/230_pythonthusiast/archive/1317_building_python_flask_application_in_openshiftheroku_replacement_part_vii__adding_sign_in_form_using_bootstrap_3_and_login_feature_using_flask-login.html") 36 | # #endif 37 | # #endif 38 | 39 | # #if TOPIC in ('Flask+Django', 'Django') 40 | 41 | # #if TOPIC == 'Flask+Django' 42 | ===== Django resources ===== 43 | # #endif 44 | 45 | * "Django webpage": "https://www.djangoproject.com/" 46 | * "List of Web tutorials": "https://code.djangoproject.com/wiki/Tutorials" 47 | * "YouTube videos": "http://www.youtube.com/playlist?list=PL385A53B00B8B158E" 48 | * "Effective Django Tutorial": "http://www.effectivedjango.com/tutorial/" 49 | * "Django by Example": "http://lightbird.net/dbe2/" (blog, questionnaire, etc.) 50 | * "Django for Scientific Applications": "http://www.blopig.com/blog/2013/09/django-for-scientific-applications/" 51 | * "A Tutorial for Deploying a Django Application that Uses Numpy and Scipy to Google Compute Engine Using Apache2 and modwsgi": "http://www.datacommunitydc.org/blog/2013/12/a-tutorial-for-deploying-a-django-application-that-uses-numpy-and-scipy-to-google-compute-engine-using-apache2-and-modwsgi" 52 | 53 | # #endif 54 | -------------------------------------------------------------------------------- /doc/src/web4sa/make.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # Compile document in HTML versions, Flask+Django, Flask only, 3 | # Django only, Sphinx version, and LaTeX/PDF version. 4 | set -x 5 | sh clean.sh 6 | 7 | function system { 8 | "$@" 9 | if [ $? -ne 0 ]; then 10 | echo "make.sh: unsuccessful command $@" 11 | echo "abort!" 12 | exit 1 13 | fi 14 | } 15 | 16 | name=web4sa 17 | 18 | system doconce format html $name -DTOPIC=Flask+Django --html_style=bloodish 19 | cp $name.html ${name}_plain_all.html 20 | cp $name.html ${name}_plain.html 21 | system doconce split_html ${name}_plain --nav_button=text 22 | 23 | system doconce format html $name -DTOPIC=Flask+Django --html_style=solarized3 24 | cp $name.html ${name}_solarized.html 25 | system doconce split_html ${name}_solarized --nav_button=text 26 | 27 | system doconce format html ${name} -DTOPIC=Flask --html_style=bootstrap --html_template=html_templates/template_flask.html --html_output=${name}_flask 28 | system doconce split_html ${name}_flask 29 | 30 | system doconce format html ${name} -DTOPIC=Django --html_style=bootstrap --html_template=html_templates/template_django.html --html_output=${name}_django 31 | system doconce split_html ${name}_django 32 | 33 | system doconce format sphinx $name -DTOPIC=Flask+Django 34 | system doconce split_rst $name 35 | system doconce sphinx_dir $name theme=cbc 36 | system python automake_sphinx.py 37 | mv sphinx-rootdir/_build/html sphinx-cbc 38 | #cd sphinx-rootdir 39 | # Note: make_themes.sh does not fix headings with numbers (1), (2) etc 40 | # such as automake_sphinx.py does 41 | #sh make_themes.sh cbc basicstrap redcloud 42 | #cd .. 43 | #mv sphinx-rootdir/sphinx-* . 44 | 45 | 46 | system doconce format pdflatex $name -DTOPIC=Flask+Django 47 | system doconce ptex2tex $name envir=minted 48 | system pdflatex -shell-escape $name 49 | makeindex $name 50 | pdflatex -shell-escape $name 51 | pdflatex -shell-escape $name 52 | 53 | doconce format html index --html_style=bootstrap --html_boostrap_jumbotron=off --html_bootstrap_navbar=off 54 | 55 | # Publish 56 | dest=../../pub 57 | rm -rf $dest/sphinx-rootdir $dest/sphinx-* 58 | rm -rf sphinx-rootdir 59 | cp -r ${name}*.html .*${name}*.html $name.pdf sphinx-* $dest 60 | cp -r fig-$name/* $dest/fig-$name/ 61 | cp index.html $dest 62 | -------------------------------------------------------------------------------- /doc/src/web4sa/publish.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | name=web4sa 3 | cp -r *.html .*.html html_templates sphinx-* $name.pdf fig-$name ../../pub/ 4 | rm -rf ../../pub/sphinx-rootdir # remove this if it was copied 5 | -------------------------------------------------------------------------------- /doc/src/web4sa/slides-web4sa/intro.do.txt: -------------------------------------------------------------------------------- 1 | !split 2 | ======= Web frameworks ======= 3 | 4 | idx{web frameworks} 5 | 6 | Goal: 7 | 8 | o generate a web page with input data to your application, 9 | o run the application to perform mathematical computations, and 10 | o generate a web page with the results of the computations. 11 | 12 | Technologies: 13 | 14 | * CGI script 15 | * Web frameworks: Django, Flask, web2py, Bottle, ... 16 | 17 | Here: 18 | 19 | # #if TOPIC == 'Flask+Django' 20 | * Intro to "Flask": "http://flask.pocoo.org/" (first) and "Django": "https://www.djangoproject.com/" 21 | # #elif TOPIC == 'Flask' 22 | * Intro to "Flask": "http://flask.pocoo.org/" 23 | # #elif TOPIC == 'Django' 24 | * Intro to "Django": "https://www.djangoproject.com/" 25 | # #endif 26 | * Focus: how to use web frameworks for *scientific applications* 27 | 28 | !split 29 | ===== Required background knowledge ===== 30 | # #if TOPIC == 'Flask+Django' 31 | * Python packages and modules, classes, decorators 32 | # #elif TOPIC == 'Flask' 33 | * Python modules, decorators 34 | # #elif TOPIC == 'Django' 35 | * Python packages and modules, classes 36 | # #endif 37 | 38 | <% 39 | github_path = 'https://github.com/hplgit/web4sciapps/tree/master/doc/src/web4sa' 40 | app_path = 'src-web4sa/apps/' 41 | %> 42 | 43 | !split 44 | ===== The code associated with these slides is on the web ===== 45 | 46 | All the files associated with this document are available in a 47 | "GitHub repository": "https://github.com/hplgit/web4sciapps/". 48 | The relevant files for the web applications are located 49 | in a subtree "`doc/src/web4sa/src-web4sa/apps`": "${github_path}/${app_path}" 50 | of this repository. 51 | 52 | !split 53 | ===== The MVC pattern for organizing the software ===== 54 | 55 | idx{MVC pattern} 56 | 57 | * MVC = Model-View-Controller 58 | * Goal: separate the user's interaction with an application from the inner 59 | workings of the application 60 | * Scientific application: separate the math from the user interface 61 | and visualization 62 | * See the "Wikipedia definition of the MVC pattern": "http://en.wikipedia.org/wiki/MVC_Pattern" 63 | * Different web frameworks interpret MCV differently... 64 | 65 | The classical MVC pattern introduces 66 | 67 | * the model to hold the data 68 | * the view to display the data 69 | * the controller to move the data by gluing the model and the view. 70 | 71 | We add for scientific applications 72 | 73 | * the *compute* component to perform mathematical computations 74 | 75 | !split 76 | ===== The MVC pattern for scientific applications ===== 77 | 78 | * The model contains the data (often only the input data) of the application, 79 | * The view controls the user interface that handles input and output data, 80 | and also calls to functionality that computes the output given the input. 81 | 82 | Implementation: 83 | * Model: a Python class with static attributes holding the data 84 | * View: Python code processing the model's data, calling the 85 | compute component, and specifying HTML 86 | templates for the design of the web pages 87 | # #if TOPIC == 'Django' 88 | * Django has files with names `models.py` and `views.py` so the 89 | model and view concepts are very explicit 90 | The controller functionality in Django lies both in the `views.py` file and 91 | in configuration files (`settings.py` and `urls.py`). The view component consists of the `views.py` file and HTML templates 92 | # #elif TOPIC == 'Flask' 93 | * Flask does not force any MVC pattern on the programmer, but 94 | the code can easily be split into 95 | model, view, controller, and compute components 96 | # #elif TOPIC == 'Flask+Django' 97 | * Django has files with names `models.py` and `views.py` so the 98 | model and view concepts are very explicit 99 | The controller functionality in Django lies both in the `views.py` file and 100 | in configuration files (`settings.py` and `urls.py`). The view component consists of the `views.py` file and HTML templates 101 | * Flask does not force any MVC pattern on the programmer, but 102 | the code can easily be split into 103 | model, view, controller, and compute components 104 | # #endif 105 | 106 | Let's learn from examples! 107 | 108 | !split 109 | ===== A very simple application ===== 110 | 111 | ## Define Mako variable for path to source code 112 | <% 113 | #src_path = '../../../src/apps/' 114 | src_path = 'src-web4sa/apps/' 115 | app_path = src_path + 'py_apps/hw_orig' 116 | %> 117 | 118 | * Start: ``scientific hello world program'' 119 | * Read a number, write ``Hello, World!'', and the sine of the number 120 | 121 | Plain Python version: 122 | 123 | @@@CODE ${app_path}/hw.py 124 | 125 | Execution: 126 | 127 | !bc sys 128 | Terminal> python hw.py 1.2 129 | Hello, World! sin(1.2)=0.932039 130 | !ec 131 | 132 | Web version: read `r` from a web page, compute the sine, 133 | and write out a new web page 134 | 135 | !split 136 | ===== Application of the MVC pattern ===== 137 | label{wf:hw:mvc} 138 | 139 | ## Define Mako variable for path to source code 140 | <% 141 | app_path = src_path + 'py_apps/hw_mvc' 142 | %> 143 | 144 | * Goal: *refactor* our program to fit the MVC pattern 145 | (with a compute component) 146 | * Method: create four modules: `model`, `view`, 147 | `compute`, and `controller`. 148 | * `compute` contains `compute(r)` that performs 149 | the mathematics and returns the value `s = sin(r)` 150 | * `model` holds the input data, here `r` 151 | * `view` contains `get_input` for reading input data 152 | and `present_output` for presenting the output 153 | (given input, it calls `compute` and 154 | generates the output) 155 | * `controller` calls the view to initialize 156 | the model's data from the command line and then calls the view 157 | to present the output 158 | 159 | !split 160 | ===== The model module contains the input data ===== 161 | 162 | @@@CODE ${app_path}/model.py 163 | 164 | !split 165 | ===== The view module holds the communication with the user ===== 166 | 167 | @@@CODE ${app_path}/view.py 168 | 169 | !split 170 | ===== The mathematics is encapsulated in the compute component ===== 171 | 172 | @@@CODE ${app_path}/compute.py 173 | 174 | !split 175 | ===== The controler glues the model and the view ===== 176 | 177 | @@@CODE ${app_path}/controller.py 178 | 179 | Let us try our refactored code: 180 | 181 | !bc sys 182 | Terminal> python controller.py 1.2 183 | Hello, World! sin(1.2)=0.932039 184 | !ec 185 | 186 | Next step: make a web interface 187 | -------------------------------------------------------------------------------- /doc/src/web4sa/slides-web4sa/links.do.txt: -------------------------------------------------------------------------------- 1 | # #if TOPIC == 'Flask+Django' 2 | ======= Resources ======= 3 | # #else 4 | ======= ${TOPIC} resources ======= 5 | # #endif 6 | 7 | # #if TOPIC in ('Flask+Django', 'Flask') 8 | 9 | # #if TOPIC == 'Flask+Django' 10 | ===== Flask resources ===== 11 | # #endif 12 | 13 | * "Flask website": "http://flask.pocoo.org/" 14 | * "Flask Quick Start": "http://flask.pocoo.org/docs/0.10/tutorial/" 15 | * "Flask tutorial": "http://flask.pocoo.org/docs/0.10/tutorial/" 16 | * "The Flask Mega-Tutorial": "http://blog.miguelgrinberg.com/post/the-flask-mega-tutorial-part-i-hello-world" by M. Grinberg 17 | * "WTForms Documentation": "http://wtforms.simplecodes.com/docs/0.6/index.html" 18 | * "The Jinja2 templating language": "http://jinja.pocoo.org/docs/" 19 | * "The Werkzeug library": "http://werkzeug.pocoo.org/" 20 | * "An Introduction to Python's Flask Framework": "http://code.tutsplus.com/tutorials/an-introduction-to-pythons-flask-framework--net-28822" by L. Polepeddi 21 | * "Discover Flask, Part I - Setting up a Static Site": "https://realpython.com/blog/python/introduction-to-flask-part-1-setting-up-a-static-site/" 22 | * Flaskr: A Minimal Blog Application: "Code": "https://github.com/mitsuhiko/flask/tree/master/examples/flaskr/", "Explanation": "https://stormpath.com/blog/build-a-flask-app-in-30-minutes/" 23 | * "Flask Login with Facebook, Twitter, and OpenID": "http://peterhudec.github.io/authomatic/examples/flask-simple.html" 24 | * "Lightweight Python Apps with Flask, Bootstrap, and Heroku": "http://blog.shea.io/lightweight-python-apps-with-flask-twitter-bootstrap-and-heroku/" by R. Shea 25 | * "How to Structure Large Flask Applications": "https://www.digitalocean.com/community/tutorials/how-to-structure-large-flask-applications" 26 | * "Explore Flask": "https://exploreflask.com/index.html" by R. Picard (online book) 27 | * "Flask Mega Tutorial for Data Scientists": "http://www.datacommunitydc.org/blog/2014/02/flask-mega-meta-tutorial-data-scientists" 28 | 29 | # #endif 30 | 31 | # #if TOPIC in ('Flask+Django', 'Django') 32 | 33 | # #if TOPIC == 'Flask+Django' 34 | ===== Django resources ===== 35 | # #endif 36 | 37 | * "Django webpage": "https://www.djangoproject.com/" 38 | * "List of Web tutorials": "https://code.djangoproject.com/wiki/Tutorials" 39 | * "YouTube videos": "http://www.youtube.com/playlist?list=PL385A53B00B8B158E" 40 | * "Effective Django Tutorial": "http://www.effectivedjango.com/tutorial/" 41 | * "Django by Example": "http://lightbird.net/dbe2/" (blog, questionnaire, etc.) 42 | * "Django for Scientific Applications": "http://www.blopig.com/blog/2013/09/django-for-scientific-applications/" 43 | * "A Tutorial for Deploying a Django Application that Uses Numpy and Scipy to Google Compute Engine Using Apache2 and modwsgi": "http://www.datacommunitydc.org/blog/2013/12/a-tutorial-for-deploying-a-django-application-that-uses-numpy-and-scipy-to-google-compute-engine-using-apache2-and-modwsgi" 44 | 45 | # #endif 46 | -------------------------------------------------------------------------------- /doc/src/web4sa/slides_web4sa.do.txt: -------------------------------------------------------------------------------- 1 | TITLE: Using Web Frameworks for Scientific Applications 2 | AUTHOR: Hans Petter Langtangen at Center for Biomedical Computing, Simula Research Laboratory & Department of Informatics, University of Oslo 3 | AUTHOR: Anders E. Johansen at Center for Biomedical Computing, Simula Research Laboratory 4 | DATE: today 5 | 6 | !split 7 | TOC: on 8 | 9 | # #include "slides-websa/intro.do.txt" 10 | 11 | # #if TOPIC in ('Flask+Django', 'Flask') 12 | # #include "slides-websa/flask_hw.do.txt" 13 | # #endif 14 | 15 | # #if TOPIC in ('Flask+Django', 'Django') 16 | # #include "slides-websa/django_hw.do.txt" 17 | # #endif 18 | 19 | # #if TOPIC in ('Flask+Django', 'Flask') 20 | # #include "slides-websa/flask_vib.do.txt" 21 | # #endif 22 | 23 | # #if TOPIC in ('Flask+Django', 'Django') 24 | # #include "slides-websa/django_vib.do.txt" 25 | # #endif 26 | 27 | # #include "slides-websa/links.do.txt" 28 | -------------------------------------------------------------------------------- /doc/src/web4sa/src-web4sa/apps/django_apps/hw1/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hplgit/web4sciapps/8d225ced1928e0706c43044429325c8ff9b01e76/doc/src/web4sa/src-web4sa/apps/django_apps/hw1/__init__.py -------------------------------------------------------------------------------- /doc/src/web4sa/src-web4sa/apps/django_apps/hw1/compute.py: -------------------------------------------------------------------------------- 1 | import math 2 | 3 | def compute(r): 4 | return math.sin(r) 5 | -------------------------------------------------------------------------------- /doc/src/web4sa/src-web4sa/apps/django_apps/hw1/models.py: -------------------------------------------------------------------------------- 1 | from django.db import models 2 | from django.forms import ModelForm 3 | 4 | class Input(models.Model): 5 | r = models.FloatField() 6 | 7 | class InputForm(ModelForm): 8 | class Meta: 9 | model = Input 10 | -------------------------------------------------------------------------------- /doc/src/web4sa/src-web4sa/apps/django_apps/hw1/templates/hw1.html: -------------------------------------------------------------------------------- 1 |
{% csrf_token %} 2 | Hello, World! The sine of {{ form.r }} 3 | 4 |
5 | -------------------------------------------------------------------------------- /doc/src/web4sa/src-web4sa/apps/django_apps/hw1/tests.py: -------------------------------------------------------------------------------- 1 | """ 2 | This file demonstrates writing tests using the unittest module. These will pass 3 | when you run "manage.py test". 4 | 5 | Replace this with more appropriate tests for your application. 6 | """ 7 | 8 | from django.test import TestCase 9 | 10 | 11 | class SimpleTest(TestCase): 12 | def test_basic_addition(self): 13 | """ 14 | Tests that 1 + 1 always equals 2. 15 | """ 16 | self.assertEqual(1 + 1, 2) 17 | -------------------------------------------------------------------------------- /doc/src/web4sa/src-web4sa/apps/django_apps/hw1/views.py: -------------------------------------------------------------------------------- 1 | from django.shortcuts import render_to_response 2 | from django.template import RequestContext 3 | from django.http import HttpResponse 4 | from models import InputForm 5 | from compute import compute 6 | 7 | def index(request): 8 | if request.method == 'POST': 9 | form = InputForm(request.POST) 10 | if form.is_valid(): 11 | form = form.save(commit=False) 12 | return present_output(form) 13 | else: 14 | form = InputForm() 15 | 16 | return render_to_response('hw1.html', 17 | {'form': form}, context_instance=RequestContext(request)) 18 | 19 | def present_output(form): 20 | r = form.r 21 | s = compute(r) 22 | return HttpResponse('Hello, World! sin(%s)=%s' % (r, s)) 23 | -------------------------------------------------------------------------------- /doc/src/web4sa/src-web4sa/apps/django_apps/hw2/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hplgit/web4sciapps/8d225ced1928e0706c43044429325c8ff9b01e76/doc/src/web4sa/src-web4sa/apps/django_apps/hw2/__init__.py -------------------------------------------------------------------------------- /doc/src/web4sa/src-web4sa/apps/django_apps/hw2/compute.py: -------------------------------------------------------------------------------- 1 | import math 2 | 3 | def compute(r): 4 | return math.sin(r) 5 | -------------------------------------------------------------------------------- /doc/src/web4sa/src-web4sa/apps/django_apps/hw2/models.py: -------------------------------------------------------------------------------- 1 | from django.db import models 2 | from django.forms import ModelForm 3 | 4 | class Input(models.Model): 5 | r = models.FloatField() 6 | 7 | class InputForm(ModelForm): 8 | class Meta: 9 | model = Input 10 | -------------------------------------------------------------------------------- /doc/src/web4sa/src-web4sa/apps/django_apps/hw2/templates/hw2.html: -------------------------------------------------------------------------------- 1 |
{% csrf_token %} 2 | Hello, World! The sine of {{ form.r }} 3 | 4 | {% if s != '' %} 5 | {{ s }} 6 | {% endif %} 7 |
8 | 9 | -------------------------------------------------------------------------------- /doc/src/web4sa/src-web4sa/apps/django_apps/hw2/views.py: -------------------------------------------------------------------------------- 1 | from django.shortcuts import render_to_response 2 | from django.template import RequestContext 3 | from django.http import HttpResponse 4 | from models import InputForm 5 | from compute import compute 6 | 7 | def index(request): 8 | s = None # initial value of result 9 | if request.method == 'POST': 10 | form = InputForm(request.POST) 11 | if form.is_valid(): 12 | form = form.save(commit=False) 13 | r = form.r 14 | s = compute(r) 15 | else: 16 | form = InputForm() 17 | 18 | return render_to_response('hw2.html', 19 | {'form': form, 20 | 's': '%.5f' % s if isinstance(s, float) else '' 21 | }, context_instance=RequestContext(request)) 22 | 23 | -------------------------------------------------------------------------------- /doc/src/web4sa/src-web4sa/apps/django_apps/vib1/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hplgit/web4sciapps/8d225ced1928e0706c43044429325c8ff9b01e76/doc/src/web4sa/src-web4sa/apps/django_apps/vib1/__init__.py -------------------------------------------------------------------------------- /doc/src/web4sa/src-web4sa/apps/django_apps/vib1/compute.py: -------------------------------------------------------------------------------- 1 | from numpy import exp, cos, linspace 2 | import matplotlib.pyplot as plt 3 | import os, time, glob 4 | 5 | def damped_vibrations(t, A, b, w): 6 | return A*exp(-b*t)*cos(w*t) 7 | 8 | def compute(A, b, w, T, resolution=500): 9 | """Return filename of plot of the damped_vibration function.""" 10 | print os.getcwd() 11 | t = linspace(0, T, resolution+1) 12 | y = damped_vibrations(t, A, b, w) 13 | plt.figure() # needed to avoid adding curves in plot 14 | plt.plot(t, y) 15 | plt.title('A=%g, b=%g, w=%g' % (A, b, w)) 16 | if not os.path.isdir('static'): 17 | os.mkdir('static') 18 | else: 19 | # Remove old plot files 20 | for filename in glob.glob(os.path.join('static', '*.png')): 21 | os.remove(filename) 22 | # Use time since Jan 1, 1970 in filename in order make 23 | # a unique filename that the browser has not chached 24 | plotfile = os.path.join('static', str(time.time()) + '.png') 25 | plt.savefig(plotfile) 26 | return plotfile 27 | 28 | if __name__ == '__main__': 29 | print compute(1, 0.1, 1, 20) 30 | -------------------------------------------------------------------------------- /doc/src/web4sa/src-web4sa/apps/django_apps/vib1/models.py: -------------------------------------------------------------------------------- 1 | from django.db import models 2 | from django.forms import ModelForm 3 | from math import pi 4 | 5 | class Input(models.Model): 6 | A = models.FloatField( 7 | verbose_name=' amplitude (m)', default=1.0) 8 | b = models.FloatField( 9 | verbose_name=' damping coefficient (kg/s)', default=0.0) 10 | w = models.FloatField( 11 | verbose_name=' frequency (1/s)', default=2*pi) 12 | T = models.FloatField( 13 | verbose_name=' time interval (s)', default=18) 14 | 15 | class InputForm(ModelForm): 16 | class Meta: 17 | model = Input 18 | -------------------------------------------------------------------------------- /doc/src/web4sa/src-web4sa/apps/django_apps/vib1/templates/vib1.html: -------------------------------------------------------------------------------- 1 |
{% csrf_token %} 2 | 3 | {% for field in form %} 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | {% endfor %} 12 |
{{ field.name }}{{ field }}{{ field.label }}{{ field.errors }}
13 |

14 | 15 |

16 | {% if result != None %} 17 | {% load static %} 18 | 19 | {% endif %} 20 |

21 | -------------------------------------------------------------------------------- /doc/src/web4sa/src-web4sa/apps/django_apps/vib1/views.py: -------------------------------------------------------------------------------- 1 | from django.shortcuts import render_to_response 2 | from django.template import RequestContext 3 | from django.http import HttpResponse 4 | from models import InputForm 5 | from compute import compute 6 | import os 7 | 8 | def index(request): 9 | os.chdir(os.path.dirname(__file__)) 10 | result = None 11 | if request.method == 'POST': 12 | form = InputForm(request.POST) 13 | if form.is_valid(): 14 | form2 = form.save(commit=False) 15 | result = compute(form2.A, form2.b, form2.w, form2.T) 16 | result = result.replace('static/', '') 17 | else: 18 | form = InputForm() 19 | 20 | return render_to_response('vib1.html', 21 | {'form': form, 22 | 'result': result, 23 | }, context_instance=RequestContext(request)) 24 | -------------------------------------------------------------------------------- /doc/src/web4sa/src-web4sa/apps/django_apps/vib2/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hplgit/web4sciapps/8d225ced1928e0706c43044429325c8ff9b01e76/doc/src/web4sa/src-web4sa/apps/django_apps/vib2/__init__.py -------------------------------------------------------------------------------- /doc/src/web4sa/src-web4sa/apps/django_apps/vib2/compute.py: -------------------------------------------------------------------------------- 1 | from numpy import exp, cos, linspace 2 | import matplotlib.pyplot as plt 3 | import os, time, glob 4 | 5 | def damped_vibrations(t, A, b, w): 6 | return A*exp(-b*t)*cos(w*t) 7 | 8 | def compute(A, b, w, T, resolution=500): 9 | """Return filename of plot of the damped_vibration function.""" 10 | print os.getcwd() 11 | t = linspace(0, T, resolution+1) 12 | y = damped_vibrations(t, A, b, w) 13 | plt.figure() # needed to avoid adding curves in plot 14 | plt.plot(t, y) 15 | plt.title('A=%g, b=%g, w=%g' % (A, b, w)) 16 | if not os.path.isdir('static'): 17 | os.mkdir('static') 18 | else: 19 | # Remove old plot files 20 | for filename in glob.glob(os.path.join('static', '*.png')): 21 | os.remove(filename) 22 | # Use time since Jan 1, 1970 in filename in order make 23 | # a unique filename that the browser has not chached 24 | plotfile = os.path.join('static', str(time.time()) + '.png') 25 | plt.savefig(plotfile) 26 | return plotfile 27 | 28 | if __name__ == '__main__': 29 | print compute(1, 0.1, 1, 20) 30 | -------------------------------------------------------------------------------- /doc/src/web4sa/src-web4sa/apps/django_apps/vib2/models.py: -------------------------------------------------------------------------------- 1 | from django.db import models 2 | from django.forms import ModelForm 3 | from math import pi 4 | from django.core.exceptions import ValidationError 5 | from django.core.validators import MinValueValidator 6 | import functools 7 | 8 | def check_interval(value, min_value=None, max_value=None): 9 | """Validate that a value is inside an interval.""" 10 | failure = False 11 | if min_value is not None: 12 | if value < min_value: 13 | failure = True 14 | if max_value is not None: 15 | if value > max_value: 16 | failure = True 17 | if failure: 18 | raise ValidationError( 19 | 'value=%s not in [%s, %s]' % 20 | (value, 21 | '-infty' if min_value is None else str(min_value), 22 | 'infty' if max_value is None else str(max_value))) 23 | 24 | def interval(min_value=None, max_value=None): 25 | """Django-compatible interface to check_interval.""" 26 | return functools.partial( 27 | check_interval, min_value=min_value, max_value=max_value) 28 | 29 | class Input(models.Model): 30 | A = models.FloatField( 31 | verbose_name=' amplitude (m)', default=1.0, 32 | validators=[MinValueValidator(0)]) 33 | b = models.FloatField( 34 | verbose_name=' damping coefficient (kg/s)', default=0.0, 35 | validators=[interval(0,None)]) 36 | w = models.FloatField( 37 | verbose_name=' frequency (1/s)', default=2*pi) 38 | T = models.FloatField( 39 | verbose_name=' time interval (s)', default=18) 40 | 41 | class InputForm(ModelForm): 42 | class Meta: 43 | model = Input 44 | 45 | def clean_T(self): 46 | T = self.cleaned_data['T'] 47 | w = self.cleaned_data['w'] 48 | period = 2*pi/w 49 | if T > 30*period: 50 | num_periods = int(round(T/period)) 51 | raise ValidationError( 52 | 'Cannot plot as much as %d periods! T<%.2f' % 53 | (num_periods, 30*period)) 54 | return T 55 | -------------------------------------------------------------------------------- /doc/src/web4sa/src-web4sa/apps/django_apps/vib2/templates/vib2.html: -------------------------------------------------------------------------------- 1 |
{% csrf_token %} 2 | 3 | {% for field in form %} 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | {% endfor %} 12 |
{{ field.name }}{{ field }}{{ field.label }}{{ field.errors }}
13 |

14 | 15 |

16 | {% if result != None %} 17 | {% load static %} 18 | 19 | {% endif %} 20 |

21 | -------------------------------------------------------------------------------- /doc/src/web4sa/src-web4sa/apps/django_apps/vib2/views.py: -------------------------------------------------------------------------------- 1 | from django.shortcuts import render_to_response 2 | from django.template import RequestContext 3 | from django.http import HttpResponse 4 | from models import InputForm 5 | from compute import compute 6 | import os 7 | 8 | def index(request): 9 | os.chdir(os.path.dirname(__file__)) 10 | result = None 11 | if request.method == 'POST': 12 | form = InputForm(request.POST) 13 | if form.is_valid(): 14 | form2 = form.save(commit=False) 15 | result = compute(form2.A, form2.b, form2.w, form2.T) 16 | result = result.replace('static/', '') 17 | else: 18 | form = InputForm() 19 | 20 | return render_to_response('vib2.html', 21 | {'form': form, 22 | 'result': result, 23 | }, context_instance=RequestContext(request)) 24 | -------------------------------------------------------------------------------- /doc/src/web4sa/src-web4sa/apps/flask_apps/gen/compute.py: -------------------------------------------------------------------------------- 1 | from numpy import exp, cos, linspace, zeros_like 2 | import matplotlib.pyplot as plt 3 | import os, time, glob, math 4 | 5 | def damped_vibrations(t, A, b, w): 6 | return A*exp(-b*t)*cos(w*t) 7 | 8 | def compute_vib(A, b, w, T, resolution=500): 9 | """Return filename of plot of the damped_vibration function.""" 10 | t = linspace(0, T, resolution+1) 11 | y = damped_vibrations(t, A, b, w) 12 | plt.figure() # needed to avoid adding curves in plot 13 | plt.plot(t, y) 14 | plt.title('A=%g, b=%g, w=%g' % (A, b, w)) 15 | 16 | # Make Matplotlib write to BytesIO file object and grab 17 | # return the object's string 18 | from io import BytesIO 19 | figfile = BytesIO() 20 | plt.savefig(figfile, format='png') 21 | figfile.seek(0) # rewind to beginning of file 22 | import base64 23 | figdata_png = base64.b64encode(figfile.getvalue()) 24 | figfile = BytesIO() 25 | plt.savefig(figfile, format='svg') 26 | figfile.seek(0) 27 | figdata_svg = ' 2 | 3 | {% for field in form %} 4 | 5 | 11 | {% endfor %} 12 |
{{ field.name }} {{ field }}{% if field.errors %} 6 |
    7 | {% for error in field.errors %} 8 |
  • {{ error }}
  • 9 | {% endfor %}
10 | {% endif %}
13 |

14 | 15 | {% if result != None %} 16 | {{ result|safe }} 17 | {% endif %} 18 | -------------------------------------------------------------------------------- /doc/src/web4sa/src-web4sa/apps/flask_apps/gen/templates/view_results.html: -------------------------------------------------------------------------------- 1 |

2 | 3 | 4 | 9 | 10 | 11 | 12 | 13 | 17 |
5 | 6 | 7 | 8 |
{{ result[2]|safe }}{{ result[3]|safe }}
14 | Mean value: {{ result[4] }}
15 | Standard deviation value: {{ result[5] }} 16 |
18 |

19 | -------------------------------------------------------------------------------- /doc/src/web4sa/src-web4sa/apps/flask_apps/gen/templates/view_results_default.html: -------------------------------------------------------------------------------- 1 |

2 | {% if result != None %} 3 | {% if type(result) == type("") and 4 | result[:-4] == '.png' or result[:-4] == '.gif' or 5 | result[:-4] == '.jpg' %} 6 | 7 | {% else %} 8 | {{ str(result) }} 9 | {% endif %} 10 | {% endif %} 11 |

12 | -------------------------------------------------------------------------------- /doc/src/web4sa/src-web4sa/apps/flask_apps/hw1/compute.py: -------------------------------------------------------------------------------- 1 | import math 2 | 3 | def compute(r): 4 | return math.sin(r) 5 | -------------------------------------------------------------------------------- /doc/src/web4sa/src-web4sa/apps/flask_apps/hw1/controller.py: -------------------------------------------------------------------------------- 1 | from flask import Flask, render_template, request 2 | from wtforms import Form, FloatField, validators 3 | from compute import compute 4 | 5 | app = Flask(__name__) 6 | 7 | # Model 8 | class InputForm(Form): 9 | r = FloatField(validators=[validators.InputRequired()]) 10 | 11 | # View 12 | @app.route('/hw1', methods=['GET', 'POST']) 13 | def index(): 14 | form = InputForm(request.form) 15 | if request.method == 'POST' and form.validate(): 16 | r = form.r.data 17 | s = compute(r) 18 | return render_template("view_output.html", form=form, s=s) 19 | else: 20 | return render_template("view_input.html", form=form) 21 | 22 | if __name__ == '__main__': 23 | app.run(debug=True) 24 | -------------------------------------------------------------------------------- /doc/src/web4sa/src-web4sa/apps/flask_apps/hw1/templates/view_input.html: -------------------------------------------------------------------------------- 1 |
2 | Hello, World! The sine of {{ form.r }} 3 | 4 |
5 | -------------------------------------------------------------------------------- /doc/src/web4sa/src-web4sa/apps/flask_apps/hw1/templates/view_output.html: -------------------------------------------------------------------------------- 1 | Hello, World! sin({{ form.r.data }})={{ s }}. 2 | -------------------------------------------------------------------------------- /doc/src/web4sa/src-web4sa/apps/flask_apps/hw2/compute.py: -------------------------------------------------------------------------------- 1 | import math 2 | 3 | def compute(r): 4 | return math.sin(r) 5 | -------------------------------------------------------------------------------- /doc/src/web4sa/src-web4sa/apps/flask_apps/hw2/controller.py: -------------------------------------------------------------------------------- 1 | from flask import Flask, render_template, request 2 | from wtforms import Form, FloatField, validators 3 | from compute import compute 4 | 5 | app = Flask(__name__) 6 | 7 | # Model 8 | class InputForm(Form): 9 | r = FloatField(validators=[validators.InputRequired()]) 10 | 11 | # View 12 | @app.route('/hw2', methods=['GET', 'POST']) 13 | def index(): 14 | form = InputForm(request.form) 15 | if request.method == 'POST' and form.validate(): 16 | r = form.r.data 17 | s = compute(r) 18 | else: 19 | s = None 20 | 21 | return render_template("view.html", form=form, s=s) 22 | 23 | if __name__ == '__main__': 24 | app.run(debug=True) 25 | -------------------------------------------------------------------------------- /doc/src/web4sa/src-web4sa/apps/flask_apps/hw2/templates/view.html: -------------------------------------------------------------------------------- 1 |
2 | Hello, World! The sine of 3 | {{( form.r )}} 4 | 5 | {% if s != None %} 6 | {{ s }} 7 | {% endif %} 8 |
9 | -------------------------------------------------------------------------------- /doc/src/web4sa/src-web4sa/apps/flask_apps/hw3/compute.py: -------------------------------------------------------------------------------- 1 | import math 2 | 3 | def compute(r): 4 | return math.sin(r) 5 | -------------------------------------------------------------------------------- /doc/src/web4sa/src-web4sa/apps/flask_apps/hw3/controller.py: -------------------------------------------------------------------------------- 1 | from flask import Flask, render_template, request 2 | from compute import compute 3 | from model import InputForm 4 | 5 | app = Flask(__name__) 6 | 7 | @app.route('/hw3', methods=['GET', 'POST']) 8 | def index(): 9 | form = InputForm(request.form) 10 | if request.method == 'POST' and form.validate(): 11 | r = form.r.data 12 | s = compute(r) 13 | else: 14 | s = None 15 | 16 | return render_template("view.html", form=form, s=s) 17 | 18 | 19 | if __name__ == '__main__': 20 | app.run(debug=True) 21 | -------------------------------------------------------------------------------- /doc/src/web4sa/src-web4sa/apps/flask_apps/hw3/model.py: -------------------------------------------------------------------------------- 1 | from wtforms import Form, FloatField, validators 2 | 3 | class InputForm(Form): 4 | r = FloatField(validators=[validators.InputRequired()]) 5 | 6 | -------------------------------------------------------------------------------- /doc/src/web4sa/src-web4sa/apps/flask_apps/hw3/templates/view.html: -------------------------------------------------------------------------------- 1 |
2 | Hello, World! The sine of 3 | {{ (form.r) }} 4 | 5 | {% if s != None %} 6 | {{ s }} 7 | {% endif %} 8 |
9 | 10 | -------------------------------------------------------------------------------- /doc/src/web4sa/src-web4sa/apps/flask_apps/login/_generate_app.py: -------------------------------------------------------------------------------- 1 | """ 2 | This file is not part of the web application in this directory. 3 | 4 | This file just applies the Parampool package to automatically generate 5 | a Flask app with login functionality. It was used as starting 6 | point for the files in this directory, but the files have been 7 | edited (and simplified) afterwards. 8 | """ 9 | from parampool.generator.flask import generate 10 | from compute import compute 11 | 12 | generate(compute, default_field='FloatField', enable_login=True) 13 | -------------------------------------------------------------------------------- /doc/src/web4sa/src-web4sa/apps/flask_apps/login/app.py: -------------------------------------------------------------------------------- 1 | import os 2 | from flask import Flask 3 | 4 | app = Flask(__name__) 5 | app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///sqlite.db' 6 | app.secret_key = os.urandom(24) 7 | 8 | # Email settings 9 | import base64 10 | app.config.update( 11 | MAIL_SERVER='smtp.gmail.com', 12 | MAIL_PORT=587, 13 | MAIL_USE_TLS=True, 14 | MAIL_USERNAME = 'cbcwebsolvermail@gmail.com', 15 | MAIL_PASSWORD = base64.decodestring('RGlmZmljdWx0UFch'), 16 | MAIL_DEFAULT_SENDER = 'Flask Compute Email ' 17 | ) 18 | -------------------------------------------------------------------------------- /doc/src/web4sa/src-web4sa/apps/flask_apps/login/compute.py: -------------------------------------------------------------------------------- 1 | from numpy import exp, cos, linspace 2 | import matplotlib.pyplot as plt 3 | import os, time, glob 4 | 5 | def damped_vibrations(t, A, b, w): 6 | return A*exp(-b*t)*cos(w*t) 7 | 8 | def compute(A, b, w, T, resolution=500): 9 | """Return filename of plot of the damped_vibration function.""" 10 | t = linspace(0, T, resolution+1) 11 | y = damped_vibrations(t, A, b, w) 12 | plt.figure() # needed to avoid adding curves in plot 13 | plt.plot(t, y) 14 | plt.title('A=%g, b=%g, w=%g' % (A, b, w)) 15 | 16 | # Make Matplotlib write to BytesIO file object and grab 17 | # return the object's string 18 | from io import BytesIO 19 | figfile = BytesIO() 20 | plt.savefig(figfile, format='png') 21 | figfile.seek(0) # rewind to beginning of file 22 | import base64 23 | figdata_png = base64.b64encode(figfile.getvalue()) 24 | return figdata_png 25 | 26 | def compute_png_svg(A, b, w, T, resolution=500): 27 | """Return filename of plot of the damped_vibration function.""" 28 | t = linspace(0, T, resolution+1) 29 | y = damped_vibrations(t, A, b, w) 30 | plt.figure() # needed to avoid adding curves in plot 31 | plt.plot(t, y) 32 | plt.title('A=%g, b=%g, w=%g' % (A, b, w)) 33 | 34 | # Make Matplotlib write to BytesIO file object and grab 35 | # return the object's string 36 | from io import BytesIO 37 | figfile = BytesIO() 38 | plt.savefig(figfile, format='png') 39 | figfile.seek(0) # rewind to beginning of file 40 | import base64 41 | figdata_png = base64.b64encode(figfile.getvalue()) 42 | figfile = BytesIO() 43 | plt.savefig(figfile, format='svg') 44 | figfile.seek(0) 45 | figdata_svg = ' 0: 43 | instance = user.Compute.order_by('-id').first() 44 | result = instance.result 45 | form = populate_form_from_instance(instance) 46 | 47 | return render_template("view.html", form=form, 48 | result=result, user=user) 49 | 50 | 51 | def populate_form_from_instance(instance): 52 | """Repopulate form with previous values""" 53 | form = ComputeForm() 54 | for field in form: 55 | field.data = getattr(instance, field.name) 56 | return form 57 | 58 | def send_email(user): 59 | from flask.ext.mail import Mail, Message 60 | mail = Mail(app) 61 | msg = Message("Compute Computations Complete", 62 | recipients=[user.email]) 63 | msg.body = """ 64 | A simulation has been completed by the Flask Compute app. 65 | Please log in at 66 | 67 | http://localhost:5000/login 68 | 69 | to see the results. 70 | 71 | --- 72 | If you don't want email notifications when a result is found, 73 | please register a new user and leave the 'notify' field 74 | unchecked. 75 | """ 76 | mail.send(msg) 77 | 78 | @app.route('/reg', methods=['GET', 'POST']) 79 | def create_login(): 80 | from forms import register_form 81 | form = register_form(request.form) 82 | if request.method == 'POST' and form.validate(): 83 | user = User() 84 | form.populate_obj(user) 85 | user.set_password(form.password.data) 86 | 87 | db.session.add(user) 88 | db.session.commit() 89 | 90 | login_user(user) 91 | return redirect(url_for('index')) 92 | return render_template("reg.html", form=form) 93 | 94 | @app.route('/login', methods=['GET', 'POST']) 95 | def login(): 96 | from forms import login_form 97 | form = login_form(request.form) 98 | if request.method == 'POST' and form.validate(): 99 | user = form.get_user() 100 | login_user(user) 101 | return redirect(url_for('index')) 102 | return render_template("login.html", form=form) 103 | 104 | @app.route('/logout') 105 | @login_required 106 | def logout(): 107 | logout_user() 108 | return redirect(url_for('index')) 109 | 110 | @app.route('/old') 111 | @login_required 112 | def old(): 113 | data = [] 114 | user = current_user 115 | if user.is_authenticated(): 116 | instances = user.Compute.order_by('-id').all() 117 | for instance in instances: 118 | form = populate_form_from_instance(instance) 119 | 120 | result = instance.result 121 | if instance.comments: 122 | comments = "

Comments

" + instance.comments 123 | else: 124 | comments = '' 125 | data.append( 126 | {'form':form, 'result':result, 127 | 'id':instance.id, 'comments': comments}) 128 | 129 | return render_template("old.html", data=data) 130 | 131 | @app.route('/add_comment', methods=['GET', 'POST']) 132 | @login_required 133 | def add_comment(): 134 | user = current_user 135 | if request.method == 'POST' and user.is_authenticated(): 136 | instance = user.Compute.order_by('-id').first() 137 | instance.comments = request.form.get("comments", None) 138 | db.session.commit() 139 | return redirect(url_for('index')) 140 | 141 | @app.route('/delete/', methods=['GET', 'POST']) 142 | @login_required 143 | def delete_post(id): 144 | id = int(id) 145 | user = current_user 146 | if user.is_authenticated(): 147 | if id == -1: 148 | instances = user.Compute.delete() 149 | else: 150 | try: 151 | instance = user.Compute.filter_by(id=id).first() 152 | db.session.delete(instance) 153 | except: 154 | pass 155 | 156 | db.session.commit() 157 | return redirect(url_for('old')) 158 | 159 | 160 | if __name__ == '__main__': 161 | if not os.path.isfile(os.path.join( 162 | os.path.dirname(__file__), 'sqlite.db')): 163 | db.create_all() 164 | app.run(debug=True) 165 | -------------------------------------------------------------------------------- /doc/src/web4sa/src-web4sa/apps/flask_apps/login/db_models.py: -------------------------------------------------------------------------------- 1 | from flask.ext.sqlalchemy import SQLAlchemy 2 | from werkzeug import generate_password_hash, check_password_hash 3 | from app import app 4 | 5 | db = SQLAlchemy(app) 6 | 7 | class User(db.Model): 8 | id = db.Column(db.Integer, primary_key=True) 9 | username = db.Column(db.String(50), unique=True) 10 | pwhash = db.Column(db.String()) 11 | email = db.Column(db.String(120), nullable=True) 12 | notify = db.Column(db.Boolean()) 13 | 14 | def __repr__(self): 15 | return '' % (self.username) 16 | 17 | def check_password(self, pw): 18 | return check_password_hash(self.pwhash, pw) 19 | 20 | def set_password(self, pw): 21 | self.pwhash = generate_password_hash(pw) 22 | 23 | def is_authenticated(self): 24 | return True 25 | 26 | def is_active(self): 27 | return True 28 | 29 | def is_anonymous(self): 30 | return False 31 | 32 | def get_id(self): 33 | return self.id 34 | 35 | class Compute(db.Model): 36 | id = db.Column(db.Integer, primary_key=True) 37 | 38 | A = db.Column(db.String()) 39 | b = db.Column(db.String()) 40 | w = db.Column(db.String()) 41 | T = db.Column(db.String()) 42 | resolution = db.Column(db.Integer) 43 | 44 | result = db.Column(db.String()) 45 | comments = db.Column(db.String(), nullable=True) 46 | user_id = db.Column(db.Integer, db.ForeignKey('user.id')) 47 | user = db.relationship('User', 48 | backref=db.backref('Compute', lazy='dynamic')) 49 | -------------------------------------------------------------------------------- /doc/src/web4sa/src-web4sa/apps/flask_apps/login/forms.py: -------------------------------------------------------------------------------- 1 | import wtforms as wtf 2 | from math import pi 3 | 4 | class ComputeForm(wtf.Form): 5 | A = wtf.FloatField(label='\( A \)', default=1.0, 6 | validators=[wtf.validators.InputRequired()]) 7 | b = wtf.FloatField(label='\( b \)', default=0.0, 8 | validators=[wtf.validators.InputRequired()]) 9 | w = wtf.FloatField(label='\( w \)', default=pi, 10 | validators=[wtf.validators.InputRequired()]) 11 | T = wtf.FloatField(label='\( T \)', default=18, 12 | validators=[wtf.validators.InputRequired()]) 13 | resolution = wtf.IntegerField(label='resolution', default=500, 14 | validators=[wtf.validators.InputRequired()]) 15 | 16 | from db_models import db, User 17 | import flask.ext.wtf.html5 as html5 18 | 19 | # Standard Forms 20 | class register_form(wtf.Form): 21 | username = wtf.TextField( 22 | label='Username', validators=[wtf.validators.Required()]) 23 | password = wtf.PasswordField( 24 | label='Password', validators=[ 25 | wtf.validators.Required(), 26 | wtf.validators.EqualTo( 27 | 'confirm', message='Passwords must match')]) 28 | confirm = wtf.PasswordField( 29 | label='Confirm Password', 30 | validators=[wtf.validators.Required()]) 31 | email = html5.EmailField(label='Email') 32 | notify = wtf.BooleanField(label='Email notifications') 33 | 34 | def validate(self): 35 | if not wtf.Form.validate(self): 36 | return False 37 | 38 | if self.notify.data and not self.email.data: 39 | self.notify.errors.append( 40 | 'Cannot send notifications without a valid email address') 41 | return False 42 | 43 | if db.session.query(User).filter_by( 44 | username=self.username.data).count() > 0: 45 | self.username.errors.append('User already exists') 46 | return False 47 | 48 | return True 49 | 50 | class login_form(wtf.Form): 51 | username = wtf.TextField( 52 | label='Username', validators=[wtf.validators.Required()]) 53 | password = wtf.PasswordField( 54 | label='Password', validators=[wtf.validators.Required()]) 55 | 56 | def validate(self): 57 | if not wtf.Form.validate(self): 58 | return False 59 | 60 | user = self.get_user() 61 | 62 | if user is None: 63 | self.username.errors.append('Unknown username') 64 | return False 65 | 66 | if not user.check_password(self.password.data): 67 | self.password.errors.append('Invalid password') 68 | return False 69 | 70 | return True 71 | 72 | def get_user(self): 73 | return db.session.query(User).filter_by( 74 | username=self.username.data).first() 75 | -------------------------------------------------------------------------------- /doc/src/web4sa/src-web4sa/apps/flask_apps/upload/compute.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import os 3 | 4 | def compute_mean_std(filename=None): 5 | data = np.loadtxt(os.path.join('uploads', filename)) 6 | return """ 7 | Data from file %s: 8 |

9 | 10 | 11 | 12 | """ % (filename, np.mean(data), np.std(data)) 13 | -------------------------------------------------------------------------------- /doc/src/web4sa/src-web4sa/apps/flask_apps/upload/controller.py: -------------------------------------------------------------------------------- 1 | from compute import compute_mean_std as compute_function 2 | 3 | from flask import Flask, render_template, request 4 | from model import Average 5 | from werkzeug import secure_filename 6 | import os 7 | 8 | # Application object 9 | app = Flask(__name__) 10 | 11 | # Relative path of directory for uploaded files 12 | UPLOAD_DIR = 'uploads/' 13 | 14 | app.config['UPLOAD_FOLDER'] = UPLOAD_DIR 15 | app.secret_key = 'MySecretKey' 16 | 17 | if not os.path.isdir(UPLOAD_DIR): 18 | os.mkdir(UPLOAD_DIR) 19 | 20 | # Allowed file types for file upload 21 | ALLOWED_EXTENSIONS = set(['txt', 'dat', 'npy']) 22 | 23 | def allowed_file(filename): 24 | """Does filename have the right extension?""" 25 | return '.' in filename and \ 26 | filename.rsplit('.', 1)[1] in ALLOWED_EXTENSIONS 27 | 28 | # Path to the web application 29 | @app.route('/', methods=['GET', 'POST']) 30 | def index(): 31 | form = Average(request.form) 32 | filename = None # default 33 | if request.method == 'POST': 34 | 35 | # Save uploaded file on server if it exists and is valid 36 | if request.files: 37 | file = request.files[form.filename.name] 38 | if file and allowed_file(file.filename): 39 | # Make a valid version of filename for any file ystem 40 | filename = secure_filename(file.filename) 41 | file.save(os.path.join(app.config['UPLOAD_FOLDER'], 42 | filename)) 43 | 44 | result = compute_function(filename) 45 | else: 46 | result = None 47 | 48 | return render_template("view.html", form=form, result=result) 49 | 50 | if __name__ == '__main__': 51 | app.run(debug=True) 52 | -------------------------------------------------------------------------------- /doc/src/web4sa/src-web4sa/apps/flask_apps/upload/model.py: -------------------------------------------------------------------------------- 1 | import wtforms as wtf 2 | 3 | class Average(wtf.Form): 4 | filename = wtf.FileField(validators= 5 | [wtf.validators.InputRequired()]) 6 | -------------------------------------------------------------------------------- /doc/src/web4sa/src-web4sa/apps/flask_apps/upload/testfile.dat: -------------------------------------------------------------------------------- 1 | 1.1 2 | 2.2 3 | 4 4 | -------------------------------------------------------------------------------- /doc/src/web4sa/src-web4sa/apps/flask_apps/vib1/compute.py: -------------------------------------------------------------------------------- 1 | from numpy import exp, cos, linspace 2 | import matplotlib.pyplot as plt 3 | import os, time, glob 4 | 5 | def damped_vibrations(t, A, b, w): 6 | return A*exp(-b*t)*cos(w*t) 7 | 8 | def compute(A, b, w, T, resolution=500): 9 | """Return filename of plot of the damped_vibration function.""" 10 | t = linspace(0, T, resolution+1) 11 | u = damped_vibrations(t, A, b, w) 12 | plt.figure() # needed to avoid adding curves in plot 13 | plt.plot(t, u) 14 | plt.title('A=%g, b=%g, w=%g' % (A, b, w)) 15 | if not os.path.isdir('static'): 16 | os.mkdir('static') 17 | else: 18 | # Remove old plot files 19 | for filename in glob.glob(os.path.join('static', '*.png')): 20 | os.remove(filename) 21 | # Use time since Jan 1, 1970 in filename in order make 22 | # a unique filename that the browser has not chached 23 | plotfile = os.path.join('static', str(time.time()) + '.png') 24 | plt.savefig(plotfile) 25 | return plotfile 26 | 27 | if __name__ == '__main__': 28 | print compute(1, 0.1, 1, 20) 29 | -------------------------------------------------------------------------------- /doc/src/web4sa/src-web4sa/apps/flask_apps/vib1/controller.py: -------------------------------------------------------------------------------- 1 | from model import InputForm 2 | from flask import Flask, render_template, request 3 | from compute import compute 4 | import sys 5 | 6 | app = Flask(__name__) 7 | 8 | try: 9 | template_name = sys.argv[1] 10 | except IndexError: 11 | template_name = 'view_plain' 12 | 13 | if template_name == 'view_flask_bootstrap': 14 | from flask_bootstrap import Bootstrap 15 | Bootstrap(app) 16 | 17 | @app.route('/vib1', methods=['GET', 'POST']) 18 | def index(): 19 | form = InputForm(request.form) 20 | if request.method == 'POST' and form.validate(): 21 | result = compute(form.A.data, form.b.data, 22 | form.w.data, form.T.data) 23 | else: 24 | result = None 25 | print form, dir(form) 26 | #print form.keys() 27 | for f in form: 28 | print f.id 29 | print f.name 30 | print f.label 31 | 32 | return render_template(template_name + '.html', 33 | form=form, result=result) 34 | 35 | if __name__ == '__main__': 36 | app.run(debug=True) 37 | -------------------------------------------------------------------------------- /doc/src/web4sa/src-web4sa/apps/flask_apps/vib1/model.py: -------------------------------------------------------------------------------- 1 | from wtforms import Form, FloatField, validators 2 | from math import pi 3 | 4 | class InputForm(Form): 5 | A = FloatField( 6 | label='amplitude (m)', default=1.0, 7 | validators=[validators.InputRequired()]) 8 | b = FloatField( 9 | label='damping factor (kg/s)', default=0, 10 | validators=[validators.InputRequired()]) 11 | w = FloatField( 12 | label='frequency (1/s)', default=2*pi, 13 | validators=[validators.InputRequired()]) 14 | T = FloatField( 15 | label='time interval (s)', default=18, 16 | validators=[validators.InputRequired()]) 17 | -------------------------------------------------------------------------------- /doc/src/web4sa/src-web4sa/apps/flask_apps/vib1/static/basic.css: -------------------------------------------------------------------------------- 1 | td.name { color: blue; } 2 | -------------------------------------------------------------------------------- /doc/src/web4sa/src-web4sa/apps/flask_apps/vib1/templates/view.html: -------------------------------------------------------------------------------- 1 |

Give input:

2 | 3 | 4 | {% for field in form %} 5 |
{{ field.name }} 6 |
{{ field|safe }} {{field.label }} 7 | {% if field.errors %} 8 |
    9 | {% for error in field.errors %} 10 |
  • {{ error }}
  • 11 | {% endfor %}
12 | {% endif %}
13 | {% endfor %} 14 |

15 | 16 |

17 | {% if result != None %} 18 |

Plot:

19 | 20 | {% endif %} 21 |

22 | -------------------------------------------------------------------------------- /doc/src/web4sa/src-web4sa/apps/flask_apps/vib1/templates/view_bootstrap.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 8 | 9 | 17 | 20 | 31 | 32 |

Damped sine wave

33 | 34 | This web page visualizes the function \( 35 | u(t) = Ae^{-bt}\sin (w t), \hbox{ for } t\in [0,T] 36 | \). 37 | 38 |

39 | 40 |

41 | {% for field in form %} 42 |
43 |
44 | 47 |
48 | {{ field(class_="form-control") }} 49 |
50 |
51 | {{ field.label }} 52 |
53 | {% if field.errors %} 54 | {% for error in field.errors %} 55 |
56 |
{{ error }}
57 |
58 | {% endfor %} 59 | {% endif %} 60 |
61 |
62 | {% endfor %} 63 |
64 | 65 | 66 | 67 |

68 | {% if result != None %} 69 | 70 | {% endif %} 71 | 72 | -------------------------------------------------------------------------------- /doc/src/web4sa/src-web4sa/apps/flask_apps/vib1/templates/view_css.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 |

mean %.3g
st.dev. %.3g
9 | {% for field in form %} 10 | 11 | 12 | 13 | 14 | {% if field.errors %} 15 | 19 | {% endif %} 20 | 21 | {% endfor %} 22 |
{{ field.name }}{{ field(size=12) }}{{ field.label }}
    16 | {% for error in field.errors %} 17 |
  • {{ error }}
  • 18 | {% endfor %}
23 |

24 | 25 |

26 | {% if result != None %} 27 | 28 | {% endif %} 29 |

30 | 31 | 32 | -------------------------------------------------------------------------------- /doc/src/web4sa/src-web4sa/apps/flask_apps/vib1/templates/view_errcheck.html: -------------------------------------------------------------------------------- 1 |
2 | 3 | {% for field in form %} 4 | 5 | 6 | 7 | {% if field.errors %} 8 | 12 | {% endif %} 13 | 14 | {% endfor %} 15 |
{{ field.name }}{{ field(size=12) }}{{ field.label }}
    9 | {% for error in field.errors %} 10 |
  • {{ error }}
  • 11 | {% endfor %}
16 |

17 |

18 | {% if result != None %} 19 | 20 | {% endif %} 21 |

22 | -------------------------------------------------------------------------------- /doc/src/web4sa/src-web4sa/apps/flask_apps/vib1/templates/view_flask_bootstrap.html: -------------------------------------------------------------------------------- 1 | {% extends "bootstrap/base.html" %} 2 | 3 | {% block styles %} 4 | {{super()}} 5 | 8 | 9 | 17 | 20 | {% endblock %} 21 | 22 | 35 | 36 | {% block content %} 37 | 38 |

Damped sine wave

39 | 40 | This web page visualizes the function \( 41 | u(t) = Ae^{-bt}\sin (w t), \hbox{ for } t\in [0,T] 42 | \). 43 | 44 |

45 |