Daniel@0: /* Part of DML (Digital Music Laboratory) Daniel@0: Copyright 2014-2015 Samer Abdallah, University of London Daniel@0: Daniel@0: This program is free software; you can redistribute it and/or Daniel@0: modify it under the terms of the GNU General Public License Daniel@0: as published by the Free Software Foundation; either version 2 Daniel@0: of the License, or (at your option) any later version. Daniel@0: Daniel@0: This program is distributed in the hope that it will be useful, Daniel@0: but WITHOUT ANY WARRANTY; without even the implied warranty of Daniel@0: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the Daniel@0: GNU General Public License for more details. Daniel@0: Daniel@0: You should have received a copy of the GNU General Public Daniel@0: License along with this library; if not, write to the Free Software Daniel@0: Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Daniel@0: */ Daniel@0: Daniel@0: :- module(api_matlab, []). Daniel@0: Daniel@0: :- use_module(library(http/http_dispatch)). Daniel@0: :- use_module(library(http/http_parameters)). Daniel@0: :- use_module(library(sandbox)). Daniel@0: :- use_module(library(insist)). Daniel@0: :- use_module(library(fileutils)). Daniel@0: :- use_module(library(swipe)). Daniel@0: :- use_module(library(httpfiles)). Daniel@0: :- use_module(library(mlserver)). Daniel@0: Daniel@0: :- set_prolog_flag(double_quotes,string). Daniel@0: :- set_prolog_flag(back_quotes,symbol_char). Daniel@0: Daniel@0: :- http_handler(api(matlab/render), figure_render, []). Daniel@0: Daniel@0: :- setting(matlab:pixels_per_inch,number,150,"Pixels per inch for in browser figures"). Daniel@0: :- setting(matlab:default_figure_format,oneof([png,svg]),svg,"Default Matlab figure rendering method"). Daniel@0: Daniel@0: :- initialization catch(mutex_create(_,[alias(matlab_fig)]),Ex,print_message(warning,Ex)). Daniel@0: Daniel@0: %% figure_render(+Request) is det. Daniel@0: % Daniel@0: % HTTP handler for rendering Matlab figures. Daniel@0: figure_render(Request) :- Daniel@0: setting(matlab:pixels_per_inch,DefPPI), Daniel@0: http_parameters(Request, Daniel@0: [ code(CodeA,[ atom, optional(false), description("Prolog rendering goal")]) Daniel@0: , format(F, [ oneof([eps,svg,pdf,png]), optional(false), description("Output format") ]) Daniel@0: , width(W, [ number, optional(true), default(10), description("Width in cm")]) Daniel@0: , height(H, [ number, optional(true), default(6), description("Height in cm")]) Daniel@0: , color_map(CMA, [ atom, optional(true), default(hot) ]) Daniel@0: , font_name(FN, [ atom, optional(true), default(helvetica) ]) Daniel@0: , font_size(FS, [ number, optional(true), default(8) ]) Daniel@0: , line_width(LW, [ number, optional(true), default(0.75) ]) Daniel@0: , marker_size(MS,[ number, optional(true), default(4) ]) Daniel@0: , ppi(PPI, [ number, optional(true), default(DefPPI), description("PNG resolution")]) Daniel@0: ]), Daniel@0: debug(matlab,"Attempting to parse \"~s\".",[CodeA]), Daniel@0: atom_to_term(CodeA,Code,[]), Daniel@0: atom_to_term(CMA,CM,[]), Daniel@0: ( user_db:logged_on(A) Daniel@0: -> debug(matlab,"Logged on as ~w, no checking",[A]) Daniel@0: ; debug(matlab,"Checking ~q for safety...",[Code]), Daniel@0: sandbox:safe_goal(Code), Daniel@0: debug(matlab,"Goal is safe.",[]) Daniel@0: ), Daniel@0: insist(with_temp_dir(Dir, ( Daniel@0: render(F,Code,Dir, [ size(W,H), ppi(PPI),color_map(CM),line_width(LW) Daniel@0: , font_name(FN),font_size(FS),marker_size(MS) ]), Daniel@0: atom_concat('tmp_.',F,Out), Daniel@0: absolute_file_name(Dir/Out,File), Daniel@0: reply_file(File,F) Daniel@0: ))). Daniel@0: Daniel@0: Daniel@0: render(eps,Code,D,Opts) :- with_mutex(matlab_fig,print_fig(Code,D,Opts,'-depsc2')). Daniel@0: render(pdf,Code,D,Opts) :- render(eps,Code,D,Opts), run(in(D,sh(0>>0, "epstopdf tmp_.eps"))). Daniel@0: render(svg,Code,D,Opts) :- render(pdf,Code,D,Opts), run(in(D,sh(0>>0, "pdf2svg tmp_.pdf tmp_.svg"))). Daniel@0: render(png,Code,D,Opts) :- Daniel@0: render(eps,Code,D,Opts), Daniel@0: option(ppi(PPI),Opts), Daniel@0: run(in(D,sh(0>>0, "gs -dBATCH -dNumRenderingThreads=2 -dEPSCrop -dNOPAUSE -sDEVICE=pngalpha -sOutputFile=tmp_.png -r~d -q tmp_.eps",[\PPI]))). Daniel@0: Daniel@0: render_fig(Code,Opts) :- Daniel@0: option(color_map(ColorMap),Opts), Daniel@0: option(font_name(FontName),Opts), Daniel@0: option(font_size(FontSize),Opts), Daniel@0: option(line_width(LineWidth),Opts), Daniel@0: option(marker_size(MarkerSize),Opts), Daniel@0: option(colour(Colour),Opts,1), Daniel@0: option(axes_line_width_ratio(LWR),Opts,0.5), Daniel@0: option(figure(Fig),Opts,99), Daniel@0: ml_async(exec( dml_paperfig(Fig,`FontName,FontSize,LineWidth,Colour,MarkerSize,LWR); Daniel@0: colormap(ColorMap)),20), Daniel@0: debug(matlab,'Calling: ~q',[Code]), Daniel@0: with_output_to(string(_),call(Code)). Daniel@0: Daniel@0: print_fig(Code,Dir,Opts,PrintOpt) :- Daniel@0: render_fig(Code,Opts), Daniel@0: debug(matlab,'Saving figure to ~w',[Dir]), Daniel@0: absolute_file_name(Dir/'tmp_',Name), Daniel@0: ( option(size(Width,Height),Opts) Daniel@0: -> ml_async(exec(dml_fsetup(Width,Height,`centimeters)),20) Daniel@0: ; true), Daniel@0: ml_async(exec(print(`PrintOpt,`Name)),120).