├── tests ├── __init__.py └── test_app.py ├── screenshot.png ├── app ├── static │ ├── img │ │ ├── icon.ico │ │ ├── segment.gif │ │ ├── snake-20x20.gif │ │ ├── broken-circle.gif │ │ ├── chasing-arrows.gif │ │ ├── spinning-line.gif │ │ ├── broken-circle-15x15.gif │ │ ├── broken-circle-20x20.gif │ │ ├── growing-ring-10x10.gif │ │ └── growing-ring-20x20.gif │ ├── fonts │ │ ├── glyphicons-halflings-regular.eot │ │ ├── glyphicons-halflings-regular.ttf │ │ ├── glyphicons-halflings-regular.woff │ │ └── glyphicons-halflings-regular.woff2 │ ├── css │ │ ├── externals │ │ │ ├── font-awesome │ │ │ │ └── fonts │ │ │ │ │ ├── FontAwesome.otf │ │ │ │ │ ├── fontawesome-webfont.eot │ │ │ │ │ ├── fontawesome-webfont.ttf │ │ │ │ │ ├── fontawesome-webfont.woff │ │ │ │ │ └── fontawesome-webfont.woff2 │ │ │ ├── rainbow │ │ │ │ ├── rainbow-linenumbers.css │ │ │ │ ├── github.css │ │ │ │ ├── rainbow.css │ │ │ │ └── monokai.css │ │ │ └── bootstrap │ │ │ │ ├── bootstrap-theme.min.css │ │ │ │ └── bootstrap-theme.min.css.map │ │ └── scaks.css │ └── js │ │ ├── scaks │ │ ├── energy_profile.js │ │ ├── scaks.js │ │ ├── job_running.js │ │ ├── report.js │ │ ├── rxn_panel.js │ │ ├── rxn_definition.js │ │ └── model_panel.js │ │ ├── externals │ │ └── rainbow │ │ │ └── rainbow.linenumbers.min.js │ │ └── form_status │ │ └── form_status.js ├── templates │ ├── 404.html │ ├── files │ │ ├── file_tree.html │ │ ├── file_path.html │ │ ├── file_buttons.html │ │ ├── file_content.html │ │ └── file_table.html │ ├── job │ │ ├── running.html │ │ ├── running_buttons.html │ │ └── running_panel.html │ ├── report │ │ ├── report.html │ │ ├── no_report.html │ │ └── report_panel.html │ ├── model │ │ ├── model.html │ │ ├── energy_profile.html │ │ ├── model_buttons.html │ │ ├── panels.html │ │ ├── rxn_table.html │ │ ├── rxn_buttons.html │ │ ├── rxn_definition.html │ │ └── model_form.html │ ├── nav │ │ ├── navtabs.html │ │ └── navbar.html │ └── base.html ├── main │ ├── errors.py │ ├── __init__.py │ ├── utils.py │ ├── report.py │ ├── job.py │ ├── files.py │ └── model.py └── __init__.py ├── .gitmodules ├── requirements.txt ├── wsgi.py ├── example ├── example_job │ ├── rxns.py │ ├── rel_energy.py │ └── model.py └── README.txt ├── config.py ├── scaks-hub ├── .gitignore ├── .README.md ├── README.rst └── supervisor.conf /tests/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PytLab/scaks-hub/HEAD/screenshot.png -------------------------------------------------------------------------------- /app/static/img/icon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PytLab/scaks-hub/HEAD/app/static/img/icon.ico -------------------------------------------------------------------------------- /app/static/img/segment.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PytLab/scaks-hub/HEAD/app/static/img/segment.gif -------------------------------------------------------------------------------- /app/static/img/snake-20x20.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PytLab/scaks-hub/HEAD/app/static/img/snake-20x20.gif -------------------------------------------------------------------------------- /app/static/img/broken-circle.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PytLab/scaks-hub/HEAD/app/static/img/broken-circle.gif -------------------------------------------------------------------------------- /app/static/img/chasing-arrows.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PytLab/scaks-hub/HEAD/app/static/img/chasing-arrows.gif -------------------------------------------------------------------------------- /app/static/img/spinning-line.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PytLab/scaks-hub/HEAD/app/static/img/spinning-line.gif -------------------------------------------------------------------------------- /app/static/img/broken-circle-15x15.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PytLab/scaks-hub/HEAD/app/static/img/broken-circle-15x15.gif -------------------------------------------------------------------------------- /app/static/img/broken-circle-20x20.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PytLab/scaks-hub/HEAD/app/static/img/broken-circle-20x20.gif -------------------------------------------------------------------------------- /app/static/img/growing-ring-10x10.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PytLab/scaks-hub/HEAD/app/static/img/growing-ring-10x10.gif -------------------------------------------------------------------------------- /app/static/img/growing-ring-20x20.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PytLab/scaks-hub/HEAD/app/static/img/growing-ring-20x20.gif -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "rxn-parser"] 2 | path = app/static/js/rxn-parser 3 | url = git@github.com:PytLab/rxn-parser.js.git 4 | -------------------------------------------------------------------------------- /app/static/fonts/glyphicons-halflings-regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PytLab/scaks-hub/HEAD/app/static/fonts/glyphicons-halflings-regular.eot -------------------------------------------------------------------------------- /app/static/fonts/glyphicons-halflings-regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PytLab/scaks-hub/HEAD/app/static/fonts/glyphicons-halflings-regular.ttf -------------------------------------------------------------------------------- /app/static/fonts/glyphicons-halflings-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PytLab/scaks-hub/HEAD/app/static/fonts/glyphicons-halflings-regular.woff -------------------------------------------------------------------------------- /app/static/fonts/glyphicons-halflings-regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PytLab/scaks-hub/HEAD/app/static/fonts/glyphicons-halflings-regular.woff2 -------------------------------------------------------------------------------- /app/static/css/externals/font-awesome/fonts/FontAwesome.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PytLab/scaks-hub/HEAD/app/static/css/externals/font-awesome/fonts/FontAwesome.otf -------------------------------------------------------------------------------- /app/static/css/externals/font-awesome/fonts/fontawesome-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PytLab/scaks-hub/HEAD/app/static/css/externals/font-awesome/fonts/fontawesome-webfont.eot -------------------------------------------------------------------------------- /app/static/css/externals/font-awesome/fonts/fontawesome-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PytLab/scaks-hub/HEAD/app/static/css/externals/font-awesome/fonts/fontawesome-webfont.ttf -------------------------------------------------------------------------------- /app/static/css/externals/font-awesome/fonts/fontawesome-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PytLab/scaks-hub/HEAD/app/static/css/externals/font-awesome/fonts/fontawesome-webfont.woff -------------------------------------------------------------------------------- /app/static/css/externals/font-awesome/fonts/fontawesome-webfont.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PytLab/scaks-hub/HEAD/app/static/css/externals/font-awesome/fonts/fontawesome-webfont.woff2 -------------------------------------------------------------------------------- /app/static/js/scaks/energy_profile.js: -------------------------------------------------------------------------------- 1 | /* Author: ShaoZhengjiang */ 2 | ;(function($) { 3 | $('.close-energy-profile').on('click.kyn', function() { 4 | $('#energy-profile').modal('toggle'); 5 | }); 6 | 7 | })(jQuery); 8 | -------------------------------------------------------------------------------- /app/templates/404.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block content %} 4 |
5 |

404 :-(

6 |
7 | {{ msg }} 8 |
9 |
10 | {% endblock %} 11 | 12 | -------------------------------------------------------------------------------- /app/templates/files/file_tree.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block content %} 4 | {% include "nav/navtabs.html" %} 5 | {% include "files/file_path.html" %} 6 | {% include "files/file_buttons.html" %} 7 | {% include "files/file_table.html" %} 8 | {% endblock %} 9 | 10 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | Flask>=0.12.2 2 | Flask-Bootstrap>=3.3.7.1 3 | Flask-Moment>=0.5.1 4 | Flask-Script>=2.0.5 5 | Flask-SQLAlchemy>=2.2 6 | gevent>=1.2.2 7 | matplotlib>=2.0.2 8 | mpi4py>=2.0.0 9 | mpmath>=0.19 10 | numpy>=1.13.0 11 | prettytable>=0.7.2 12 | scipy>=0.19.1 13 | SQLAlchemy>=1.1.10 14 | sympy>=1.0 15 | scaks 16 | 17 | -------------------------------------------------------------------------------- /wsgi.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | import os 5 | 6 | from manager import create_app 7 | import datetime 8 | 9 | app = create_app(os.getenv('KYN-CONFIG') or 'default') 10 | 11 | @app.context_processor 12 | def template_extras(): 13 | return {'enumerate': enumerate, 'len': len, 'datetime': datetime} 14 | 15 | -------------------------------------------------------------------------------- /app/templates/job/running.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block content %} 4 | {% include "nav/navtabs.html" %} 5 | {% include "files/file_path.html" %} 6 | {% include "job/running_panel.html" %} 7 | {% endblock %} 8 | 9 | {% block script %} 10 | {{ super() }} 11 | 12 | {% endblock %} 13 | -------------------------------------------------------------------------------- /app/templates/report/report.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block content %} 4 | {% include "nav/navtabs.html" %} 5 | {% include "files/file_path.html" %} 6 | {% include "report/report_panel.html" %} 7 | {% endblock %} 8 | 9 | {% block script %} 10 | {{ super() }} 11 | 12 | {% endblock %} 13 | -------------------------------------------------------------------------------- /example/example_job/rxns.py: -------------------------------------------------------------------------------- 1 | # This file was automatically generated by KinLab (https://github.com/PytLab/KinLab). 2 | # Version 0.1.0 3 | # Date: Fri Jul 28 23:56:34 2017 4 | # 5 | # Do not make changes to this file unless you know what you are doing 6 | 7 | rxn_expressions = [ 8 | 'CO_g + *_s -> CO_s', 9 | 'O2_g + 2*_s -> 2O_s', 10 | 'CO_s + O_s <-> CO-O_2s -> CO2_g + 2*_s', 11 | ] 12 | 13 | -------------------------------------------------------------------------------- /app/templates/model/model.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block content %} 4 | {% include "nav/navtabs.html" %} 5 | {% include "files/file_path.html" %} 6 | {% include "model/panels.html" %} 7 | {% endblock %} 8 | 9 | {% block script %} 10 | {{ super() }} 11 | 16 | {% endblock %} 17 | 18 | -------------------------------------------------------------------------------- /app/templates/files/file_path.html: -------------------------------------------------------------------------------- 1 | 2 |
3 | 9 |
10 | 11 | -------------------------------------------------------------------------------- /app/main/errors.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | from flask import render_template 5 | 6 | from . import main 7 | 8 | # User-defined exception classes. 9 | class PathError(Exception): 10 | pass 11 | 12 | 13 | # View functions for error handling. 14 | @main.errorhandler(PathError) 15 | def path_not_found(error): 16 | msg, = error.args 17 | return render_template('404.html', msg=msg) 18 | 19 | -------------------------------------------------------------------------------- /app/templates/nav/navtabs.html: -------------------------------------------------------------------------------- 1 | 2 |
3 | 9 |
10 | 11 | -------------------------------------------------------------------------------- /app/templates/job/running_buttons.html: -------------------------------------------------------------------------------- 1 | 13 | -------------------------------------------------------------------------------- /app/templates/nav/navbar.html: -------------------------------------------------------------------------------- 1 | 2 | 15 | 16 | -------------------------------------------------------------------------------- /example/example_job/rel_energy.py: -------------------------------------------------------------------------------- 1 | # This file was automatically generated by KinLab (https://github.com/PytLab/KinLab). 2 | # Version 0.1.0 3 | # Date: Fri Jul 28 23:56:34 2017 4 | # 5 | # Do not make changes to this file unless you know what you are doing 6 | 7 | Ga, dG = [], [] 8 | 9 | # CO_g + *_s -> CO_s 10 | Ga.append(0.0) 11 | dG.append(-2.09) 12 | 13 | # O2_g + 2*_s -> 2O_s 14 | Ga.append(0.07) 15 | dG.append(-2.39) 16 | 17 | # CO_s + O_s <-> CO-O_2s -> CO2_g + 2*_s 18 | Ga.append(0.39) 19 | dG.append(-0.46) 20 | -------------------------------------------------------------------------------- /app/templates/report/no_report.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block content %} 4 | {% include "nav/navtabs.html" %} 5 | {% include "files/file_path.html" %} 6 |
7 |
8 |
Report
9 |
10 |
11 | Can't generate report in current directory 12 |
13 |
14 |
15 | {% endblock %} 16 | -------------------------------------------------------------------------------- /app/templates/model/energy_profile.html: -------------------------------------------------------------------------------- 1 | 2 | 14 | -------------------------------------------------------------------------------- /app/main/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | ''' Blueprint 5 | ''' 6 | 7 | import time 8 | 9 | from flask import Blueprint 10 | 11 | main = Blueprint('main', __name__) 12 | 13 | __version__ = '0.1.0' 14 | 15 | FILE_HEADER = ( 16 | '# This file was automatically generated by KinLab' + 17 | ' (https://github.com/PytLab/KinLab).\n' + 18 | '# Version %s\n# Date: %s \n#\n' + 19 | '# Do not make changes to this file ' + 20 | 'unless you know what you are doing\n\n') % (__version__, time.asctime()) 21 | 22 | from .files import * 23 | from .model import * 24 | from .job import * 25 | from .report import * 26 | 27 | -------------------------------------------------------------------------------- /example/README.txt: -------------------------------------------------------------------------------- 1 | # This is a demo for KinLab, a chemical kinetic simulation webapp powered by Kynetix 2 | 3 | * Run an example job in `/example_job` 4 | 1. go to `/example_job` 5 | 2. click `Create or open a job` button to open an existing model setting panel 6 | 3. do something on the panel or leave it unchanged 7 | 4. click the `Run` button to run the model 8 | 5. after the job finished, click the `Generate report` to check the result report 9 | 10 | * Create your own job 11 | 1. go to `empty_job` 12 | 2. do something to create your own micro kinetic model 13 | 3. run the model in the same way mentioned above 14 | 15 | Good Luck! 16 | -------------------------------------------------------------------------------- /app/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | from flask import Flask, render_template 5 | from flask_moment import Moment 6 | 7 | from config import config 8 | 9 | # Initialize plugins. 10 | moment = Moment() 11 | 12 | # App factory function. 13 | def create_app(config_name): 14 | ''' Create an app from a specific configure. 15 | ''' 16 | app = Flask(__name__) 17 | app.config.from_object(config[config_name]) 18 | config[config_name].init_app(app) 19 | 20 | # Register blueprint. 21 | from .main import main as main_blueprint 22 | app.register_blueprint(main_blueprint) 23 | 24 | moment.init_app(app) 25 | 26 | return app 27 | 28 | -------------------------------------------------------------------------------- /app/static/css/externals/rainbow/rainbow-linenumbers.css: -------------------------------------------------------------------------------- 1 | pre { 2 | padding: 0; 3 | font-family: 'Monaco', 'Source Code Pro', monospace; 4 | font-size: 1em; 5 | } 6 | .rainbow { 7 | border-spacing: 0; 8 | border-collapse: collapse; 9 | } 10 | .rainbow .line:hover { 11 | background-color: #171b1c; 12 | } 13 | .rainbow .line:hover .line-number { 14 | background-color: #101313; 15 | } 16 | .rainbow .line .line-number { 17 | text-align: right; 18 | background-color: #1b2022; 19 | padding-left: 0.8em; 20 | padding-right: 0.8em; 21 | } 22 | .rainbow .line .line-number:before { 23 | content: attr(data-line-number); 24 | } 25 | .rainbow .line .line-code { 26 | padding-left: 1em; 27 | width: 100%; 28 | } 29 | -------------------------------------------------------------------------------- /app/templates/model/model_buttons.html: -------------------------------------------------------------------------------- 1 | 2 |
3 |
4 | Run 5 | 6 | 7 | 8 |
9 |
10 | 11 |
12 |
13 | -------------------------------------------------------------------------------- /example/example_job/model.py: -------------------------------------------------------------------------------- 1 | # This file was automatically generated by kynetix-webapp (https://github.com/PytLab/kynetix-webapp). 2 | # Version 0.1.0 3 | # Date: Tue Jul 4 19:59:08 2017 4 | # 5 | # Do not make changes to this file unless you know what you are doing 6 | 7 | # Gas pressure. 8 | species_definitions = {} 9 | species_definitions['CO_g'] = {'pressure': 1.32e-07} 10 | species_definitions['O2_g'] = {'pressure': 5.26e-07} 11 | species_definitions['CO2_g'] = {'pressure': 1.32e-07} 12 | 13 | # Site info. 14 | species_definitions['*_s'] = {'type': 'site', 'total': 1.0} 15 | 16 | #Temperature. 17 | temperature = 500.0 # K 18 | 19 | parser = 'RelativeEnergyParser' 20 | solver = 'SteadyStateSolver' 21 | corrector = 'ThermodynamicCorrector' 22 | plotter = 'EnergyProfilePlotter' 23 | 24 | unitcell_area = 9e-20 25 | active_ratio = 0.4444444444444444 26 | 27 | rate_algo = 'CT' 28 | rootfinding = 'MDNewton' 29 | tolerance = 1.000000e-50 30 | max_rootfinding_iterations = 100 31 | -------------------------------------------------------------------------------- /tests/test_app.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | import unittest 4 | 5 | from flask import url_for, current_app 6 | 7 | from app import create_app 8 | 9 | class FlaskClientTest(unittest.TestCase): 10 | def setUp(self): 11 | self.app = create_app('testing') 12 | self.app_context = self.app.app_context() 13 | self.app_context.push() 14 | self.client = self.app.test_client(use_cookies=True) 15 | 16 | def tearDown(self): 17 | self.app_context.pop() 18 | 19 | def test_app_exists(self): 20 | self.assertFalse(current_app is None) 21 | 22 | def test_app_is_testing(self): 23 | self.assertTrue(current_app.config['TESTING']) 24 | 25 | def test_filetree_page(self): 26 | " Make sure the file tree page can be returned correctly. " 27 | response = self.client.get(url_for('main.filetree')) 28 | 29 | self.assertTrue('app' in response.get_data(as_text=True)) 30 | self.assertTrue('config.py' in response.get_data(as_text=True)) 31 | self.assertTrue('manager.py' in response.get_data(as_text=True)) 32 | 33 | -------------------------------------------------------------------------------- /app/static/js/externals/rainbow/rainbow.linenumbers.min.js: -------------------------------------------------------------------------------- 1 | window.Rainbow&&(window.Rainbow.linenumbers=function(m){function k(a){if(a.nodeType===Node.TEXT_NODE){a=a.nodeValue.split("\n");for(var b=[],c=0;c 2 |
3 | 6 | 7 |
8 |
9 | 10 | 11 | 14 | 15 |
16 |
17 |
18 |
19 | -------------------------------------------------------------------------------- /app/templates/files/file_content.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block content %} 4 | {% include "nav/navtabs.html" %} 5 | {% include "files/file_path.html" %} 6 | 7 | 8 |
9 |
10 |
11 |
12 | {{ filename }} 13 |
14 |
15 | {{ moment(mtime).format('LLL') }} 16 |
17 |
18 | {{ filesize }} 19 |
20 |
21 |
22 |
23 | 24 | 25 |
26 | {% if file_content %} 27 |
{{ file_content }}
28 | {% else %} 29 |
30 |
The file is empty (。_。)...
31 |
32 | {% endif %} 33 |
34 | {% endblock %} 35 | 36 | -------------------------------------------------------------------------------- /scaks-hub: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | import os 4 | 5 | from flask_script import Manager, Shell 6 | 7 | from gevent import monkey 8 | from gevent.pywsgi import WSGIServer 9 | monkey.patch_all() 10 | 11 | from app import create_app 12 | 13 | app = create_app(os.getenv('KYN-CONFIG') or 'default') 14 | manager = Manager(app) 15 | 16 | @manager.command 17 | def test(): 18 | """ Run unit tests. 19 | """ 20 | import unittest 21 | tests = unittest.TestLoader().discover('tests') 22 | unittest.TextTestRunner(verbosity=2).run(tests) 23 | 24 | @manager.command 25 | def runserver(host='127.0.0.1', port=5000): 26 | """ Run a gevent-based WSGIServer. 27 | """ 28 | port = int(port) 29 | 30 | server = WSGIServer(listener=(host, port), application=app) 31 | 32 | def serve(): 33 | print(' * Running on http://{}:{}'.format(host, port)) 34 | server.serve_forever() 35 | 36 | serve() 37 | 38 | def make_shell_context(): 39 | return dict(app=app) 40 | 41 | manager.add_command('shell', Shell(make_context=make_shell_context)) 42 | 43 | if __name__ == '__main__': 44 | import webbrowser 45 | webbrowser.open('http://localhost:5000', new=2) 46 | manager.run() 47 | 48 | -------------------------------------------------------------------------------- /app/main/utils.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | import os 5 | from datetime import datetime 6 | from functools import wraps 7 | 8 | from .errors import PathError 9 | 10 | # Utility functions. 11 | 12 | def convert_bytes(size): 13 | ''' Convert size in bytes to KB, MB... GB... etc. 14 | ''' 15 | for unit in ['bytes', 'KB', 'MB', 'GB', 'TB', 'PB']: 16 | if size < 1024.0: 17 | return '{:3.1f} {}'.format(size, unit) 18 | size /= 1024.0 19 | 20 | 21 | def check_file_exists(func): 22 | ''' Decorator for file existance checking. 23 | ''' 24 | @wraps(func) 25 | def wrapper(file_path): 26 | if not os.path.exists(file_path): 27 | raise PathError('No such file: {}'.format(file_path)) 28 | return func(file_path) 29 | return wrapper 30 | 31 | 32 | @check_file_exists 33 | def file_size(file_path): 34 | ''' Get the file size in proper size unit. 35 | ''' 36 | if os.path.isfile(file_path): 37 | size_in_bytes = os.path.getsize(file_path) 38 | return convert_bytes(size_in_bytes) 39 | 40 | 41 | @check_file_exists 42 | def file_ctime(file_path): 43 | ''' Get the creation time of a file. 44 | ''' 45 | ctime = os.path.getctime(file_path) 46 | return datetime.fromtimestamp(ctime) 47 | 48 | 49 | @check_file_exists 50 | def file_mtime(file_path): 51 | ''' Get the modification time of a file. 52 | ''' 53 | ctime = os.path.getmtime(file_path) 54 | return datetime.fromtimestamp(ctime) 55 | 56 | -------------------------------------------------------------------------------- /app/templates/model/panels.html: -------------------------------------------------------------------------------- 1 |
2 | 3 |
4 |
5 |
6 |
7 | Reaction Definition 8 |
9 |
10 |
11 |
12 | {% include "model/rxn_buttons.html" %} 13 | {% include "model/rxn_table.html" %} 14 | 15 | 16 |
17 | Loading... 18 |
19 |
20 |
21 |
22 | {% include "model/rxn_definition.html" %} 23 | {% include "model/energy_profile.html" %} 24 | 25 |
26 |
27 |
28 | Kinetic Model Definition 29 |
30 |
31 |
32 |
33 | {% include "model/model_buttons.html" %} 34 | {% include "model/model_form.html" %} 35 |
36 |
37 |
38 |
39 | -------------------------------------------------------------------------------- /app/templates/job/running_panel.html: -------------------------------------------------------------------------------- 1 |
2 | 3 |
4 |
5 | 29 |
30 | {% include "job/running_buttons.html" %} 31 |
32 |
33 | Loading log... 34 |
35 |
36 |
37 | -------------------------------------------------------------------------------- /app/static/js/scaks/scaks.js: -------------------------------------------------------------------------------- 1 | /* Author: ShaoZhengjiang */ 2 | 3 | ;(function($){ 4 | "use restrict"; 5 | 6 | /* Refresh the file table asynchronously */ 7 | $("#refresh-file-table").click(function(){ 8 | // Show loading animation. 9 | var ajax_load = '
' + 10 | '
'; 11 | $("#file-table").html(ajax_load); 12 | 13 | // Get new file table using ajax. 14 | $.get(window.location.pathname, {}, function(data, textStatus){ 15 | var file_table_html = $(data).find("#file-table").html(); 16 | $("#file-table").html(file_table_html); 17 | 18 | // Re-render time stamps using moment api. 19 | moment.locale("en"); 20 | 21 | function flask_moment_render(elem) { 22 | $(elem).text(eval('moment("' + $(elem).data('timestamp') + '").' + 23 | $(elem).data('format') + ';')); 24 | $(elem).removeClass('flask-moment').show(); 25 | } 26 | 27 | function flask_moment_render_all() { 28 | $('.flask-moment').each(function() { 29 | flask_moment_render(this); 30 | if ($(this).data('refresh')) { 31 | (function(elem, interval) { 32 | setInterval(function() { flask_moment_render(elem) }, interval); 33 | })(this, $(this).data('refresh')); 34 | } 35 | }) 36 | } 37 | 38 | flask_moment_render_all(); 39 | }); 40 | }); 41 | 42 | $('#open-job').on('click.kyn', function(event) { 43 | event.preventDefault(); 44 | }); 45 | 46 | })(jQuery); 47 | 48 | -------------------------------------------------------------------------------- /app/templates/model/rxn_table.html: -------------------------------------------------------------------------------- 1 | 2 | {% if rxn_infos %} 3 |