Commit a4b19f02 authored by FAGES Francois's avatar FAGES Francois
Browse files

merge

parents 3b90dbf7 d7bd9ceb
ADDITIONAL_MODULES=modules/sbml/sbml_utils.pl
MODULES=$(shell sed -n -E 's/^- (.*\.pl)$$/\1/p' toc.org) $(ADDITIONAL_MODULES)
MODULES=$(shell sed -n -E 's/^[+-] (.*\.pl)$$/\1/p' toc.org) \
$(ADDITIONAL_MODULES)
# load_test_files/1 should make this useless, but I cannot find how to use it
TEST_MODULES=$(wildcard $(MODULES:.pl=.plt))
......@@ -60,6 +61,9 @@ biocham_tests: swipl-biocham $(MODULES) $(TEST_MODULES) Makefile
--goal="call_cleanup((run_tests, halt(0)), halt(1))" \
-c $(MODULES) $(TEST_MODULES)
jupyter: biocham
jupyter kernelspec install --user --name=biocham biocham_kernel
clean:
- make -C modules/graphviz clean
- make -C modules/sbml clean
......
if __name__ == '__main__':
from ipykernel.kernelapp import IPKernelApp
from .kernel import BiochamKernel
IPKernelApp.launch_instance(kernel_class=BiochamKernel)
import base64
import os
# TODO: add logo-64x64.png
def display_data_for_image(filename):
with open(filename, 'rb') as f:
image = f.read()
os.unlink(filename)
image_type = filename.split('.')[-1]
if image_type == 'svg':
image_type = 'image/svg+xml'
image_data = image.decode('utf-8')
elif image_type == 'csv':
image_type = 'text/html'
image = image.decode('utf-8')
lines = [line.split(',') for line in image.splitlines()]
labels = ', '.join(['"' + label + '"' for label in lines.pop(0)[1:]])
series = '[' + ', '.join([
'[' +
', '.join(['[' + lines[i][0] + ', ' + lines[i][j] + ']'
for i in range(len(lines))]) +
']' for j in range(1, len(lines[0]))]) + ']'
plotid = filename.split('.')[-2]
image_data = '''
<div id="{plotid}" style="height: 400px; width: 600px;"></div>
<script>
function waitForJQplot() {{
if (typeof $.jqplot !== 'undefined') {{
$.jqplot.config.enablePlugins = true;
$.jqplot('{plotid}', {data}, {{
seriesDefaults: {{
showMarker: false
}},
legend: {{
show: true,
placement: "outside",
labels: [{labels}],
renderer: $.jqplot.EnhancedLegendRenderer,
rendererOptions: {{
seriesToggle: true,
showLineStyle: true
}}
}},
cursor: {{
show: true,
zoom: true,
tooltipFormatString: "%.2e, %.2e",
cursorLegendFormatString: "%.2e, %.2e"
}},
highlighter: {{
formatString: "%.2e"
}}
}});
$('#{plotid}').contextmenu(function() {{
$('#{plotid}').jqplotSaveImage();
return false;
}});
}} else {{ window.setTimeout(waitForJQplot, 250); }}
}}
$(document).ready(function(){{
waitForJQplot();
}});
</script>
'''.format(plotid=plotid, data=series, labels=labels)
else:
image_type = 'image/' + image_type
image_data = base64.b64encode(image).decode('ascii')
content = {
'data': {
image_type: image_data
},
'metadata': {}
}
return content
def extract_image_filenames(output):
output_lines = []
image_filenames = []
for line in output.split("\n"):
if line.startswith('<img src="'):
filename = line.rstrip().split('"')[1]
image_filenames.append(filename)
else:
output_lines.append(line)
output = "\n".join(output_lines)
return image_filenames, output
This diff is collapsed.
/**
* jqPlot
* Pure JavaScript plotting plugin using jQuery
*
* Version: 1.0.9
* Revision: d96a669
*
* Copyright (c) 2009-2016 Chris Leonello
* jqPlot is currently available for use in all personal or commercial projects
* under both the MIT (http://www.opensource.org/licenses/mit-license.php) and GPL
* version 2.0 (http://www.gnu.org/licenses/gpl-2.0.html) licenses. This means that you can
* choose the license that best suits your project and use it accordingly.
*
* Although not required, the author would appreciate an email letting him
* know of any substantial use of jqPlot. You can reach the author at:
* chris at jqplot dot com or see http://www.jqplot.com/info.php .
*
* If you are feeling kind and generous, consider supporting the project by
* making a donation at: http://www.jqplot.com/donate.php .
*
* sprintf functions contained in jqplot.sprintf.js by Ash Searle:
*
* version 2007.04.27
* author Ash Searle
* http://hexmen.com/blog/2007/03/printf-sprintf/
* http://hexmen.com/js/sprintf.js
* The author (Ash Searle) has placed this code in the public domain:
* "This code is unrestricted: you are free to use it however you like."
*
*/
(function($) {
// class $.jqplot.EnhancedLegendRenderer
// Legend renderer which can specify the number of rows and/or columns in the legend.
$.jqplot.EnhancedLegendRenderer = function(){
$.jqplot.TableLegendRenderer.call(this);
};
$.jqplot.EnhancedLegendRenderer.prototype = new $.jqplot.TableLegendRenderer();
$.jqplot.EnhancedLegendRenderer.prototype.constructor = $.jqplot.EnhancedLegendRenderer;
// called with scope of legend.
$.jqplot.EnhancedLegendRenderer.prototype.init = function(options) {
// prop: numberRows
// Maximum number of rows in the legend. 0 or null for unlimited.
this.numberRows = null;
// prop: numberColumns
// Maximum number of columns in the legend. 0 or null for unlimited.
this.numberColumns = null;
// prop: seriesToggle
// false to not enable series on/off toggling on the legend.
// true or a fadein/fadeout speed (number of milliseconds or 'fast', 'normal', 'slow')
// to enable show/hide of series on click of legend item.
this.seriesToggle = 'normal';
// prop: seriesToggleReplot
// True to replot the chart after toggling series on/off.
// This will set the series show property to false.
// This allows for rescaling or other maniplation of chart.
// Set to an options object (e.g. {resetAxes: true}) for replot options.
this.seriesToggleReplot = false;
// prop: disableIEFading
// true to toggle series with a show/hide method only and not allow fading in/out.
// This is to overcome poor performance of fade in some versions of IE.
this.disableIEFading = true;
$.extend(true, this, options);
if (this.seriesToggle) {
$.jqplot.postDrawHooks.push(postDraw);
}
};
// called with scope of legend
$.jqplot.EnhancedLegendRenderer.prototype.draw = function(offsets, plot) {
var legend = this;
if (this.show) {
var series = this._series;
var s;
var ss = 'position:absolute;';
ss += (this.background) ? 'background:'+this.background+';' : '';
ss += (this.border) ? 'border:'+this.border+';' : '';
ss += (this.fontSize) ? 'font-size:'+this.fontSize+';' : '';
ss += (this.fontFamily) ? 'font-family:'+this.fontFamily+';' : '';
ss += (this.textColor) ? 'color:'+this.textColor+';' : '';
ss += (this.marginTop != null) ? 'margin-top:'+this.marginTop+';' : '';
ss += (this.marginBottom != null) ? 'margin-bottom:'+this.marginBottom+';' : '';
ss += (this.marginLeft != null) ? 'margin-left:'+this.marginLeft+';' : '';
ss += (this.marginRight != null) ? 'margin-right:'+this.marginRight+';' : '';
this._elem = $('<table class="jqplot-table-legend" style="'+ss+'"></table>');
if (this.seriesToggle) {
this._elem.css('z-index', '3');
}
var pad = false,
reverse = false,
nr, nc;
if (this.numberRows) {
nr = this.numberRows;
if (!this.numberColumns){
nc = Math.ceil(series.length/nr);
}
else{
nc = this.numberColumns;
}
}
else if (this.numberColumns) {
nc = this.numberColumns;
nr = Math.ceil(series.length/this.numberColumns);
}
else {
nr = series.length;
nc = 1;
}
var i, j, tr, td1, td2, lt, rs, div, div0, div1;
var idx = 0;
// check to see if we need to reverse
for (i=series.length-1; i>=0; i--) {
if (nc == 1 && series[i]._stack || series[i].renderer.constructor == $.jqplot.BezierCurveRenderer){
reverse = true;
}
}
for (i=0; i<nr; i++) {
tr = $(document.createElement('tr'));
tr.addClass('jqplot-table-legend');
if (reverse){
tr.prependTo(this._elem);
}
else{
tr.appendTo(this._elem);
}
for (j=0; j<nc; j++) {
if (idx < series.length && (series[idx].show || series[idx].showLabel)){
s = series[idx];
lt = this.labels[idx] || s.label.toString();
if (lt) {
var color = s.color;
if (!reverse){
if (i>0){
pad = true;
}
else{
pad = false;
}
}
else{
if (i == nr -1){
pad = false;
}
else{
pad = true;
}
}
rs = (pad) ? this.rowSpacing : '0';
td1 = $(document.createElement('td'));
td1.addClass('jqplot-table-legend jqplot-table-legend-swatch');
td1.css({textAlign: 'center', paddingTop: rs});
div0 = $(document.createElement('div'));
div0.addClass('jqplot-table-legend-swatch-outline');
div1 = $(document.createElement('div'));
div1.addClass('jqplot-table-legend-swatch');
div1.css({backgroundColor: color, borderColor: color});
td1.append(div0.append(div1));
td2 = $(document.createElement('td'));
td2.addClass('jqplot-table-legend jqplot-table-legend-label');
td2.css('paddingTop', rs);
// td1 = $('<td class="jqplot-table-legend" style="text-align:center;padding-top:'+rs+';">'+
// '<div><div class="jqplot-table-legend-swatch" style="background-color:'+color+';border-color:'+color+';"></div>'+
// '</div></td>');
// td2 = $('<td class="jqplot-table-legend" style="padding-top:'+rs+';"></td>');
if (this.escapeHtml){
td2.text(lt);
}
else {
td2.html(lt);
}
if (reverse) {
if (this.showLabels) {td2.prependTo(tr);}
if (this.showSwatches) {td1.prependTo(tr);}
}
else {
if (this.showSwatches) {td1.appendTo(tr);}
if (this.showLabels) {td2.appendTo(tr);}
}
if (this.seriesToggle) {
// add an overlay for clicking series on/off
// div0 = $(document.createElement('div'));
// div0.addClass('jqplot-table-legend-overlay');
// div0.css({position:'relative', left:0, top:0, height:'100%', width:'100%'});
// tr.append(div0);
var speed;
if (typeof(this.seriesToggle) === 'string' || typeof(this.seriesToggle) === 'number') {
if (!$.jqplot.use_excanvas || !this.disableIEFading) {
speed = this.seriesToggle;
}
}
if (this.showSwatches) {
td1.bind('click', {series:s, speed:speed, plot: plot, replot:this.seriesToggleReplot}, handleToggle);
td1.addClass('jqplot-seriesToggle');
}
if (this.showLabels) {
td2.bind('click', {series:s, speed:speed, plot: plot, replot:this.seriesToggleReplot}, handleToggle);
td2.addClass('jqplot-seriesToggle');
}
// for series that are already hidden, add the hidden class
if (!s.show && s.showLabel) {
td1.addClass('jqplot-series-hidden');
td2.addClass('jqplot-series-hidden');
}
}
pad = true;
}
}
idx++;
}
td1 = td2 = div0 = div1 = null;
}
}
return this._elem;
};
var handleToggle = function (ev) {
var d = ev.data,
s = d.series,
replot = d.replot,
plot = d.plot,
speed = d.speed,
sidx = s.index,
showing = false;
if (s.canvas._elem.is(':hidden') || !s.show) {
showing = true;
}
var doLegendToggle = function() {
if (replot) {
var opts = {};
if ($.isPlainObject(replot)) {
$.extend(true, opts, replot);
}
plot.replot(opts);
// if showing, there was no canvas element to fade in, so hide here
// and then do a fade in.
if (showing && speed) {
var s = plot.series[sidx];
if (s.shadowCanvas._elem) {
s.shadowCanvas._elem.hide().fadeIn(speed);
}
s.canvas._elem.hide().fadeIn(speed);
s.canvas._elem.nextAll('.jqplot-point-label.jqplot-series-'+s.index).hide().fadeIn(speed);
}
}
else {
var s = plot.series[sidx];
if (s.canvas._elem.is(':hidden') || !s.show) {
// Not sure if there is a better way to check for showSwatches and showLabels === true.
// Test for "undefined" since default values for both showSwatches and showLables is true.
if (typeof plot.options.legend.showSwatches === 'undefined' || plot.options.legend.showSwatches === true) {
plot.legend._elem.find('td').eq(sidx * 2).addClass('jqplot-series-hidden');
}
if (typeof plot.options.legend.showLabels === 'undefined' || plot.options.legend.showLabels === true) {
plot.legend._elem.find('td').eq((sidx * 2) + 1).addClass('jqplot-series-hidden');
}
}
else {
if (typeof plot.options.legend.showSwatches === 'undefined' || plot.options.legend.showSwatches === true) {
plot.legend._elem.find('td').eq(sidx * 2).removeClass('jqplot-series-hidden');
}
if (typeof plot.options.legend.showLabels === 'undefined' || plot.options.legend.showLabels === true) {
plot.legend._elem.find('td').eq((sidx * 2) + 1).removeClass('jqplot-series-hidden');
}
}
}
};
s.toggleDisplay(ev, doLegendToggle);
};
// called with scope of plot.
var postDraw = function () {
if (this.legend.renderer.constructor == $.jqplot.EnhancedLegendRenderer && this.legend.seriesToggle){
var e = this.legend._elem.detach();
this.eventCanvas._elem.after(e);
}
};
})(jQuery);
This diff is collapsed.
This diff is collapsed.
.jqplot-xaxis,.jqplot-xaxis-label{margin-top:10px}.jqplot-x2axis,.jqplot-x2axis-label{margin-bottom:10px}.jqplot-target{position:relative;color:#666;font-family:"Trebuchet MS",Arial,Helvetica,sans-serif;font-size:1em}.jqplot-axis{font-size:.75em}.jqplot-yaxis{margin-right:10px}.jqplot-y2axis,.jqplot-y3axis,.jqplot-y4axis,.jqplot-y5axis,.jqplot-y6axis,.jqplot-y7axis,.jqplot-y8axis,.jqplot-y9axis,.jqplot-yMidAxis{margin-left:10px;margin-right:10px}.jqplot-axis-tick,.jqplot-x2axis-tick,.jqplot-xaxis-tick,.jqplot-y2axis-tick,.jqplot-y3axis-tick,.jqplot-y4axis-tick,.jqplot-y5axis-tick,.jqplot-y6axis-tick,.jqplot-y7axis-tick,.jqplot-y8axis-tick,.jqplot-y9axis-tick,.jqplot-yMidAxis-tick,.jqplot-yaxis-tick{position:absolute;white-space:pre}.jqplot-xaxis-tick{top:0;left:15px;vertical-align:top}.jqplot-x2axis-tick{bottom:0;left:15px;vertical-align:bottom}.jqplot-yaxis-tick{right:0;top:15px;text-align:right}.jqplot-yaxis-tick.jqplot-breakTick{right:-20px;margin-right:0;padding:1px 5px;z-index:2;font-size:1.5em}.jqplot-x2axis-label,.jqplot-xaxis-label,.jqplot-yMidAxis-label,.jqplot-yaxis-label{font-size:11pt;position:absolute}.jqplot-y2axis-tick,.jqplot-y3axis-tick,.jqplot-y4axis-tick,.jqplot-y5axis-tick,.jqplot-y6axis-tick,.jqplot-y7axis-tick,.jqplot-y8axis-tick,.jqplot-y9axis-tick{left:0;top:15px;text-align:left}.jqplot-yMidAxis-tick{text-align:center;white-space:nowrap}.jqplot-yaxis-label{margin-right:10px}.jqplot-y2axis-label,.jqplot-y3axis-label,.jqplot-y4axis-label,.jqplot-y5axis-label,.jqplot-y6axis-label,.jqplot-y7axis-label,.jqplot-y8axis-label,.jqplot-y9axis-label{font-size:11pt;margin-left:10px;position:absolute}.jqplot-meterGauge-tick{font-size:.75em;color:#999}.jqplot-meterGauge-label{font-size:1em;color:#999}table.jqplot-table-legend{margin:12px}table.jqplot-cursor-legend,table.jqplot-table-legend{background-color:rgba(255,255,255,.6);border:1px solid #ccc;position:absolute;font-size:.75em}td.jqplot-table-legend{vertical-align:middle}td.jqplot-seriesToggle:active,td.jqplot-seriesToggle:hover{cursor:pointer}.jqplot-table-legend .jqplot-series-hidden{text-decoration:line-through}div.jqplot-table-legend-swatch-outline{border:1px solid #ccc;padding:1px}div.jqplot-table-legend-swatch{width:0;height:0;border-width:5px 6px;border-style:solid}.jqplot-title{top:0;left:0;padding-bottom:.5em;font-size:1.2em}table.jqplot-cursor-tooltip{border:1px solid #ccc;font-size:.75em}.jqplot-canvasOverlay-tooltip,.jqplot-cursor-tooltip,.jqplot-highlighter-tooltip{border:1px solid #ccc;font-size:.75em;white-space:nowrap;background:rgba(208,208,208,.5);padding:1px}.jqplot-point-label{font-size:.75em;z-index:2}td.jqplot-cursor-legend-swatch{vertical-align:middle;text-align:center}div.jqplot-cursor-legend-swatch{width:1.2em;height:.7em}.jqplot-error{text-align:center}.jqplot-error-message{position:relative;top:46%;display:inline-block}div.jqplot-bubble-label{font-size:.8em;padding-left:2px;padding-right:2px;color:rgb(20%,20%,20%)}div.jqplot-bubble-label.jqplot-bubble-label-highlight{background:rgba(90%,90%,90%,.7)}div.jqplot-noData-container{text-align:center;background-color:rgba(96%,96%,96%,.3)}
\ No newline at end of file
define(function() {
var onload = function() {
$.ajaxSetup({ cache: true });
$.getScript("/kernelspecs/biocham/jquery.jqplot.js").done(function() {
$.getScript("/kernelspecs/biocham/jqplot.cursor.js");
$.getScript("/kernelspecs/biocham/jqplot.highlighter.js");
$.getScript("/kernelspecs/biocham/jqplot.enhancedLegendRenderer.js");
});
var cssNode = document.createElement('link');
cssNode.type = 'text/css';
cssNode.rel = 'stylesheet';
cssNode.href = '/kernelspecs/biocham/jquery.jqplot.min.css';
document.head.appendChild(cssNode);
}
return {onload: onload}
})
{
"argv": ["python3", "-m", "biocham_kernel", "-f", "{connection_file}"],
"display_name": "Biocham"
}
from subprocess import check_output
from ipykernel.kernelbase import Kernel
from pexpect import replwrap
from .images import extract_image_filenames, display_data_for_image
class BiochamKernel(Kernel):
implementation = 'Biocham'
implementation_version = '0.1.0'
language = 'biocham'
language_info = {
'name': 'biocham',
'mimetype': 'text/plain',
'file_extension': '.bc',
}
banner = check_output(['biocham4', '--version']).decode('utf-8')
language_version = banner.split()[1]
def __init__(self, **kwargs):
Kernel.__init__(self, **kwargs)
self._start_biocham()
def _start_biocham(self):
self.biocham = replwrap.REPLWrapper(
'biocham4 --jupyter',
'biocham: ',
None
)
def do_execute(self, code, silent, store_history=True,
user_expressions=None, allow_stdin=False):
output = self.biocham.run_command(code)
image_filenames, output = extract_image_filenames(output)
if not silent:
stream_content = {'name': 'stdout', 'text': output}
self.send_response(self.iopub_socket, 'stream', stream_content)
for filename in image_filenames:
try:
data = display_data_for_image(filename)
except ValueError as e:
message = {'name': 'stdout', 'text': str(e)}
self.send_response(self.iopub_socket, 'stream', message)
else:
self.send_response(self.iopub_socket, 'display_data', data)
return {'status': 'ok',
# The base class increments the execution count
'execution_count': self.execution_count,
'payload': [],
'user_expressions': {},
}
# TODO: do_complete
......@@ -60,6 +60,17 @@ option('', '--generate-doc', Arg, Arg) :-
generate_doc,
quit.
option('', '--version', Arg, Arg) :-
quit.
option('', '--jupyter', Arg, Arg) :-
set_counter(graph_svg, 0),
set_counter(plot_csv, 0),
set_plot_driver(gnu_plot_csv),
set_image_viewer_driver(img_tag),
set_draw_graph_driver(graph_svg).
add_files(Files) :-
\+ (
member(File, Files),
......
......@@ -62,7 +62,7 @@ check_conservations :-
'checks all conservation laws against reactions, and if necessary kinetics
(see also \\command{add_conservation/1}).'
),
compute_ode,
ode_system,
forall(
(
% model: current_model? compute_ode already supposes a single model
......
......@@ -245,6 +245,10 @@ read_toc(Stream, Type) :-
;
atom_codes(Atom, Line),
(
atom_concat('%', _, Atom)
->
true
;
atom_concat('* ', Section, Atom)
->
add_section(1, Section)
......@@ -257,7 +261,7 @@ read_toc(Stream, Type) :-
->
add_section(3, Section)
;
Atom = '+ index'
Atom = '- index'
->
assertz(toc(index))
;
......
......@@ -10,6 +10,7 @@
delete_vertex/1,
edge/1,
add_edge/1,
edgeref/1,
delete_edge/1,
list_edges/0,
list_isolated_vertices/0,
......@@ -116,15 +117,22 @@ add_edge(EdgeList) :-
).
delete_edge(EdgeList) :-
:- grammar(edgeref).