From b7007223bd7c99b9d92911c66411b2143a791ce4 Mon Sep 17 00:00:00 2001 From: John Ciolfi Date: Mon, 10 Apr 2023 16:05:31 -0400 Subject: [PATCH] matlab and org mode example --- examples/matlab-and-org-mode/.gitignore | 1 + .../css/styles-from-org.css | 3331 +++++++++++++++++ examples/matlab-and-org-mode/css/styles.css | 33 + .../matlab-and-org-mode.html | 440 +++ .../matlab-and-org-mode.org | 169 + examples/matlab-and-org-mode/sinewave.png | Bin 0 -> 16705 bytes 6 files changed, 3974 insertions(+) create mode 100644 examples/matlab-and-org-mode/.gitignore create mode 100644 examples/matlab-and-org-mode/css/styles-from-org.css create mode 100644 examples/matlab-and-org-mode/css/styles.css create mode 100644 examples/matlab-and-org-mode/matlab-and-org-mode.html create mode 100644 examples/matlab-and-org-mode/matlab-and-org-mode.org create mode 100644 examples/matlab-and-org-mode/sinewave.png diff --git a/examples/matlab-and-org-mode/.gitignore b/examples/matlab-and-org-mode/.gitignore new file mode 100644 index 0000000..397b4a7 --- /dev/null +++ b/examples/matlab-and-org-mode/.gitignore @@ -0,0 +1 @@ +*.log diff --git a/examples/matlab-and-org-mode/css/styles-from-org.css b/examples/matlab-and-org-mode/css/styles-from-org.css new file mode 100644 index 0000000..c09b134 --- /dev/null +++ b/examples/matlab-and-org-mode/css/styles-from-org.css @@ -0,0 +1,3331 @@ + diff --git a/examples/matlab-and-org-mode/css/styles.css b/examples/matlab-and-org-mode/css/styles.css new file mode 100644 index 0000000..746c730 --- /dev/null +++ b/examples/matlab-and-org-mode/css/styles.css @@ -0,0 +1,33 @@ +/* + * Used by ../*.org via + * #+HTML_HEAD_EXTRA: + */ + +body { + font-size: 11pt; + text-align: left; + line-height:1.2em; +} + +h1 {font-size: 14pt;} + +.title { + padding-bottom: 7px; + margin-bottom: 20px; + border-bottom: 1px solid #222; +} + +h2 { + font-size: 12pt; + padding-bottom: 4px; + margin-top: 5px; + margin-bottom: 5px; + border-bottom: 1px solid #DDD; +} + +h3 {font-size: 11pt; color: #0000ff;} +h4 {font-size: 9pt; color: #a34d32;} + +a {text-decoration: none; color: #537d7b} +a:visited {text-decoration: none; color: #98855b} +a:hover {text-decoration: underline; color: #a34d32} diff --git a/examples/matlab-and-org-mode/matlab-and-org-mode.html b/examples/matlab-and-org-mode/matlab-and-org-mode.html new file mode 100644 index 0000000..808d35b --- /dev/null +++ b/examples/matlab-and-org-mode/matlab-and-org-mode.html @@ -0,0 +1,440 @@ + + + + + + + + + + + + + + + + +
+ +
+

1 Overview

+
+

+Org-mode and matlab-mode provide a very efficient and effective system for creating scientific +documents which contain MATLAB code and/or Simulink models along with the results of these. The +results of running MATLAB code or simulating Simulink models is placed into the org-mode file by +org-mode using org babel. Org babel is org-mode's ability to execute source code within org-mode +files and optionally insert the results back in to the org-mode file. You define source code in code +blocks, e.g. +

+ +
+#+begin_src LANGUAGE <OPTIONS>
+  <CODE>
+#+end_src
+
+
+
+ +
+

2 Example

+
+

+With org-mode you can embed semantically colored code such as MATLAB within your document and +semantically edit it using "Org -> Editing -> Edit Source Example" menu or C-c '. For example, +here's a MATLAB enumeration class: +

+ +
+
classdef WeekDays
+   enumeration
+       Monday, Tuesday, Wednesday, Thursday, Friday
+   end
+end
+
+
+ +

+You can use org-mode babel to evaluate MATLAB code blocks. For example, if you type C-c C-c in the +code block, org-mode will evaluate the code in the *MATLAB* session and insert the value of ans +just below the code block. +

+ +
+
a=1+3+5+7;
+ans=a
+
+
+ +
+16
+
+ + +

+You can also use org-mode babel evaluate MATLAB code blocks to plot and insert figures back in +to this file. For example: +

+ +
+
t=[0:.1:2*pi];
+y=sin(t);
+plot(t,y);
+
+
+ + +
+

sinewave.png +

+
+
+
+
+

3 HTML Export

+
+

+You need the htmlize package to get coloring in HTML. +

+ +

+We set the "#+html_head_extra" properties above to configure CSS. We used M-x +org-html-htmlize-generate-css to create ./css/styles-from-org.css and added our customizations in +./css/styles.css. +

+
+
+ +
+

4 Setup

+
+

+The following is known to work with Emacs 27 which includes org-mode 9.3. It is also know to work +with Emacs 27 and org-mode 9.6.1. +

+ +

+To use matlab-mode with org-mode, you need to configure org-mode for matlab-mode. See README.org to +install matlab-mode. +

+ +

+We configure matlab-mode to use buffer name *MATLAB* and we alter org-mode to use this buffer by +adding the following to your ~/.emacs. +

+ +
+
;;-----------------------------------------------------------------------------------------;;
+;; org babel for matlab - make all matlab code blocks execute in the same *MATLAB* session ;;
+;;-----------------------------------------------------------------------------------------;;
+
+;; A better approach to setting org-babel-load-languages is to customize it:
+;;   M-x customize-variable RET org-babel-load-languages RET
+;; However, we are doing this here to illustrate how matlab interacts with org
+(setq org-babel-load-languages '((emacs-lisp . t)
+                                 (matlab . t)))
+
+(setq org-babel-default-header-args:matlab '((:session . "*MATLAB*")))
+
+(defun matlab-org-session-advice (orig-fun &rest args)
+  "Advice for org to reuse the *MATLAB* buffer"
+  ;; ob-octave.el leverages both org-babel-matlab-emacs-link-wrapper-method and
+  ;; org-babel-octave-wrapper-method when interacting with the *MATLAB* buffer.
+  ;; Here we fix a couple items such as adding cd default-directory:
+  (setq org-babel-matlab-emacs-link-wrapper-method
+        (concat "\
+    cd('" default-directory "');
+    %s
+    if ~exist('ans','var') ans=''; end
+    if ischar(ans), fid = fopen('%s', 'w'); fprintf(fid, '%%s\\n', ans); fclose(fid);
+    else, save -ascii %s ans
+    end
+    delete('%s')
+    "))
+  (setq org-babel-octave-wrapper-method
+        (concat "\
+    cd('" default-directory "');
+    %s
+    if ~exist('ans','var') ans=''; end
+    if ischar(ans) || isstring(ans), fid = fopen('%s', 'w'); fprintf(fid, '%%s\\n', ans); fclose(fid);
+    else, dlmwrite('%s', ans, '\\t')
+    end"))
+  (apply orig-fun args))
+
+(defun matlab-org-fixup-print (orig-fun session body result-type &optional matlabp)
+  "Fixup figure print to make it work with MATLAB"
+  ;; org 9.3 correctly does:     print -dpng figure.png
+  ;; org 9.6.1 incorrectly does: print -dpng "figure.png"
+  ;; and thus 9.6.1 creates on disk a file name containing quotes which is incorrect, so this
+  ;; advice fixes that.
+  (setq body (replace-regexp-in-string "^\\(print -dpng \\)\"\\([^\"]+\\)\"" "\\1\\2"  body t))
+  (funcall orig-fun session body result-type matlabp))
+
+(defun org-export-dispatch-no-babel-advice (orig-fun &rest args)
+  "Instruct babel to not evaluate code blocks (and hence no
+prompt) during export, e.g. conversion of org to say html."
+  (let* ((org-babel-default-header-args
+          (cons '(:eval . "never-export") org-babel-default-header-args))
+         (result (apply orig-fun args)))
+    result))
+
+(eval-after-load 'ox
+  '(progn
+     ;; Make C-c C-e `org-export-dispatch' work without prompting to evaluate code blocks
+     (advice-add 'org-export-dispatch :around #'org-export-dispatch-no-babel-advice)))
+
+;; org babel for matlab - make all matlab code blocks execute in the same *MATLAB* session
+(eval-after-load "org"
+  '(progn
+     (advice-add 'org-babel-octave-evaluate-external-process :around #'matlab-org-session-advice)
+     (advice-add 'org-babel-octave-evaluate-session :around #'matlab-org-session-advice)
+     (advice-add 'org-babel-octave-evaluate :around #'matlab-org-fixup-print)))
+
+
+ +

+To try this using "stock" emacs, place the above in org-matlab-setup.el and use: +

+ +
+emacs -q -L /path/to/matlab-mode -l /path/to/matlab-load.el -l org-matlab-setup.el
+
+
+
+
+
+

Author: John Ciolfi

+

Created: 2023-04-10 Mon 15:58

+

Validate

+
+ + diff --git a/examples/matlab-and-org-mode/matlab-and-org-mode.org b/examples/matlab-and-org-mode/matlab-and-org-mode.org new file mode 100644 index 0000000..d45fa65 --- /dev/null +++ b/examples/matlab-and-org-mode/matlab-and-org-mode.org @@ -0,0 +1,169 @@ +# // File: matlab-emacs-src/examples/matlab-and-org-mode/matlab-and-org-mode.org +# // Abstract: +# // Use this as a template for creating org-files with MATLAB and other language code blocks + +#+startup: showall +#+startup: inlineimages // C-c C-x C-v to toggle, C-c C-x C-M-v to redisplay +#+startup: latexpreview // C-c C-x C-l to toggle + +#+html_head_extra: +#+html_head_extra: +#+options: ^:{} +#+options: toc:nil +#+latex_header: \usepackage[margin=0.5in]{geometry} +#+latex_header: \usepackage{parskip} +#+latex_header: \usepackage{tocloft} +#+latex_header: \advance\cftsecnumwidth 0.5em\relax +#+latex_header: \advance\cftsubsecindent 0.5em\relax +#+latex_header: \advance\cftsubsecnumwidth 0.5em\relax + +* Overview + +[[https://orgmode.org/][Org-mode]] and [[https://sourceforge.net/projects/matlab-emacs/][matlab-mode]] provide an efficient and effective system for creating scientific documents +which contain MATLAB code and/or Simulink models along with the results of these. The results of +running MATLAB code or simulating Simulink models is placed into the org-mode file by org-mode using +org babel. [[https://orgmode.org/worg/org-contrib/babel/][Org babel]] is org-mode's ability to execute source code within org-mode files and +optionally insert the results back in to the org-mode file. You define source code in code blocks, +e.g. + + : #+begin_src LANGUAGE + : + : #+end_src + +* Example + +With org-mode you can embed semantically colored code such as MATLAB within your document and +semantically edit it using "Org -> Editing -> Edit Source Example" menu or =C-c '=. For example, +here's a MATLAB [[https://www.mathworks.com/help/matlab/enumeration-classes.html][enumeration class]]: + +#+begin_src matlab + classdef WeekDays + enumeration + Monday, Tuesday, Wednesday, Thursday, Friday + end + end +#+end_src + +You can use org-mode babel to evaluate MATLAB code blocks. For example, if you type =C-c C-c= in the +following code block, org-mode will evaluate the code in the =*MATLAB*= session and insert the value +of =ans= just below the code block. + +#+begin_src matlab :exports both :results verbatim + a=1+3+5+7; + ans=a +#+end_src + +#+RESULTS: +: 16 + +You can also use org-mode babel evaluate MATLAB code blocks to plot and insert figures back in to +this file. For example: + +#+begin_src matlab :file sinewave.png :exports both :results file graphics + t=[0:.1:2*pi]; + y=sin(t); + plot(t,y); +#+end_src + +#+RESULTS: +[[file:sinewave.png]] +* Export to HTML, PDF, etc. + +You need the htmlize package to get coloring. + +For HTML export we set the "#+html_head_extra" properties above to configure CSS. We used ~M-x +org-html-htmlize-generate-css~ to create ./css/styles-from-org.css and added our customizations in +./css/styles.css. + +For PDF export we configured several "#+latex_header" properties above. + +After this setup, you can use the "Org -> Export/Publish" or ~C-c C-e~ to export to HTML, PDF, etc. + +See the example *.html in this directory. + +* Setup + +The following is known to work with Emacs 27 which includes org-mode 9.3. It is also know to work +with Emacs 27 and org-mode 9.6.1. + +To use matlab-mode with org-mode, you need to configure org-mode for matlab-mode. See [[file:../../README.org][README.org]] to +install matlab-mode. + +We configure matlab-mode to use buffer name =*MATLAB*= and we alter org-mode to use this buffer by +adding the following to your =~/.emacs=. + +#+begin_src emacs-lisp + ;;-----------------------------------------------------------------------------------------;; + ;; org babel for matlab - make all matlab code blocks execute in the same *MATLAB* session ;; + ;;-----------------------------------------------------------------------------------------;; + + ;; A better approach to setting org-babel-load-languages is to customize it: + ;; M-x customize-variable RET org-babel-load-languages RET + ;; However, we are doing this here to illustrate how matlab interacts with org + (setq org-babel-load-languages '((emacs-lisp . t) + (matlab . t))) + + (setq org-babel-default-header-args:matlab '((:session . "*MATLAB*"))) + + (defun matlab-org-session-advice (orig-fun &rest args) + "Advice for org to reuse the *MATLAB* buffer" + ;; ob-octave.el leverages both org-babel-matlab-emacs-link-wrapper-method and + ;; org-babel-octave-wrapper-method when interacting with the *MATLAB* buffer. + ;; Here we fix a couple items such as adding cd default-directory: + (setq org-babel-matlab-emacs-link-wrapper-method + (concat "\ + cd('" default-directory "'); + %s + if ~exist('ans','var') ans=''; end + if ischar(ans), fid = fopen('%s', 'w'); fprintf(fid, '%%s\\n', ans); fclose(fid); + else, save -ascii %s ans + end + delete('%s') + ")) + (setq org-babel-octave-wrapper-method + (concat "\ + cd('" default-directory "'); + %s + if ~exist('ans','var') ans=''; end + if ischar(ans) || isstring(ans), fid = fopen('%s', 'w'); fprintf(fid, '%%s\\n', ans); fclose(fid); + else, dlmwrite('%s', ans, '\\t') + end")) + (apply orig-fun args)) + + (defun matlab-org-fixup-print (orig-fun session body result-type &optional matlabp) + "Fixup figure print to make it work with MATLAB" + ;; org 9.3 correctly does: print -dpng figure.png + ;; org 9.6.1 incorrectly does: print -dpng "figure.png" + ;; and thus 9.6.1 creates on disk a file name containing quotes which is incorrect, so this + ;; advice fixes that. + (setq body (replace-regexp-in-string "^\\(print -dpng \\)\"\\([^\"]+\\)\"" "\\1\\2" body t)) + (funcall orig-fun session body result-type matlabp)) + + (defun org-export-dispatch-no-babel-advice (orig-fun &rest args) + "Instruct babel to not evaluate code blocks (and hence no + prompt) during export, e.g. conversion of org to say html." + (let* ((org-babel-default-header-args + (cons '(:eval . "never-export") org-babel-default-header-args)) + (result (apply orig-fun args))) + result)) + + (eval-after-load 'ox + '(progn + ;; Make C-c C-e `org-export-dispatch' work without prompting to evaluate code blocks + (advice-add 'org-export-dispatch :around #'org-export-dispatch-no-babel-advice))) + + ;; org babel for matlab - make all matlab code blocks execute in the same *MATLAB* session + (eval-after-load "org" + '(progn + (advice-add 'org-babel-octave-evaluate-external-process :around #'matlab-org-session-advice) + (advice-add 'org-babel-octave-evaluate-session :around #'matlab-org-session-advice) + (advice-add 'org-babel-octave-evaluate :around #'matlab-org-fixup-print))) +#+end_src + +To try this using "stock" emacs, place the above in org-matlab-setup.el and use: + + : emacs -q -L /path/to/matlab-mode -l /path/to/matlab-load.el -l org-matlab-setup.el + +# LocalWords: showall inlineimages latexpreview usepackage parskip tocloft cftsecnumwidth sinewave +# LocalWords: cftsubsecindent cftsubsecnumwidth setq defun isstring fixup matlabp dpng funcall +# LocalWords: progn htmlize diff --git a/examples/matlab-and-org-mode/sinewave.png b/examples/matlab-and-org-mode/sinewave.png new file mode 100644 index 0000000000000000000000000000000000000000..f2ec6c1ae39ba61421cd0f5099e8a59a495ebda9 GIT binary patch literal 16705 zcmd^nXH-Lo5D}0Jk~2tp-@?7Od!KX9z4zA}Z)3`s^&MpIlnrWkLzmDZs*vJ zAPB8CLE|KXP&gw9c^nNnd=uzZJq-WBoFf=rKoC|&^nYXy=^x=PgxXX4m?rfw<#r|k zjv&trZTJfBscGnW%H7`6$LhQta!gfUM^$Y+HN+Y3Wi;5 za6b;cU;VtDm8X-t8&==R)eeym7g0TTUgUuI0ZFWcw4CHYxdSo=?SV=NfMx{j&dBm9@47C~^mNSQCRf(+Ysa6TovUijAcWCK^G&*SS?2~AC>Wg0NV~c> z!IAIyd(r(@q-q&)m+tL;-WP$ry`4Jp4(*<6t%qqMqO9&_-4?iX*-^T4fK%{h;O0v& znNO6 z$Nz7C=oYnY8%b>+3z~YpR8m^1Y5VTl9^+&Rm=HzAfs|cb2hS}}_wHa7-MMq;Ug6x_ z+^;t%;TpA0LGAox>6DDDtVO`Y^M)HDttBilecU$>NJ(XR(aL@P`c=;1{hgE)HU{mZ zN16QN;Ucbbw>+{(8dhZm-614?_m9=rFLrXU`J&lKN-?2$cWFezV^mrfBmxr`1^)hSoj`jjkC>H zE0z*5+>T)sV11`AtDtpwTx=VHoh8KEoON*toT+Aw%vYGL|1h|cw?Kgq84|EomWN~FwhMek z5Osdl%J@W{G}ZolVe}Y8T$B+XQ%k>UAEp{biLmX)FjCpvT7HPtAV*@NC^7sJMuGbD zI5H$cJuKWR<$%&Yngj%~;Zv<-)8XP}4ksYQ(0HsB@*pm5yBZ#;*b76WYW-tqGD zYD@m=LlzilMhN_M>vP{$ug!-T@$(J0W=>djh;bp7=#7a<{r9Zl?R|wc5rk7!izDcw zEvlpw;+wgnO-luR(ayT#v6*6TwUl4&hE)Z3`PAtIr`S;-^AVI7ZmXq6Lv(m%e5z_< z1VShSjQgi*Sa@tRk&6`_0yXqQJ~w7L%}9oLhEZZB7tnFYgmD>GV#y%F942lUMu=x;?p=jIkxRZa43t#;owO2qLJ zC5HCgPn(D04OEC@80BRG|4cZSm=J=kga<)r>*)KcDG?2G*k2lI4i4F^qn^d4+S=OD zEF$%djXO8KL_|dNtWWx!$uqqi9eq?!??Y45^A49@;m`9a7LgYZGz?wZhG@jBFxj3y z{W*e`lZuKe@pi!C_`8ON&f*IWrlzLfDe}!<{~Wm&mnQG?o^<|uMd;hNZ@J~YzXh*O zSmm&#(8H`^t#y>D-CSJui-EgHI3+(Ld z?yqKQU~%iEDHNam{P=_NX5hk) @Y412o+qYm~~?bv}t;jatU<(iPL5R8mEKHfiS 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%0DyDu*vCuo zMqN8!G`V|#9}hYA*a8>;XHO={M9^Mhu-%`Vb^o;s`99uKR;V{Xncay!^6tj z-rg?zj3rKBUmbZfGC7GBhIx7xeP+ZDt462*5sX>nnF7faU-3W$`xKHd z;EYfLv}kiR%eFRsecS=+?C2DxD*!T{=Mh-Vp^_RzVfUW0E;o{Jr=$2spR&1BJ>_+M z4Ip~JiH-I3-!8?e`N^05QA-`NxfD|FJ99VcZEfvlmGW9u`Nmke0BYZ6@Sye9=J~S9 z$~|ZE=`aTqNht+|9H$PX%U1JjSEr=--08mCWA zPQqdWglIO-o_jJ+3RxwgRok$jQS#lhu}IR2W@xL zpqWQ4Z^$bELHWs->SO2U_dxSXN?^CYc<}^=Q0Zm zuZ^iKgXz`CyD=RJxCL}A*ZH#4`-?k6QN@GZZ;$dGqr+NEt(m$ZA)EK&lwjd^z#1Mi zHQw(Fo0ksVQRo{5%{HL-5~~srRhU~6iR5gST(gT;$rR3;n3^^w6;MpyHmI$xUhgbl z?}Yc><>uq+nrm=+v^IuaGErG!u2Hf~^LEnt5@GSy z3$1}j4fUkzRhny=SN^4{D9`JVKM78bQuFv`l$UQRZ_X({&(pN2FOJ(4**_tcdeB3y z_-OH?qU7&_`}Q3vW*dOuU6iL8P|wTd>Mh0-|8qInTFbd-p%oe(q`6I0d_l_Fe{sTFAw64*KXsDD!f%jS>8zLjsRud?2^$;1xjS0A>zIBrRDhZd3<9OKCeKc5gzXI7 zwu41OQxnSjmlhYly2$jD%yt+BI*Nr!{nHw}nBACP4vZI|vL-EP(P*%d9W2#1P~>(} z!+ZP-A3xR0=@X(fcByfayT1P_kY9r;UG%V?Y{;B!*&kK%5q(!>yXh0AAZLa>PW#{s zAE+kVw{M3rfyh2#0tZ8C<9OrZ;>7muZGI}lcIof-qQ~J)0_xqAqcU?NBOx3b@MY{quQd#w zg)pO|Q#Ae@JE9tK*u!H63)r7a@yLLKa0{!->9iMJa}(cU?8vV zX0tk7%cCGLFO#0Nl`Z#0!#Z5;LS@$5ZYA2$C7uJM^7RSGLW3aOLzUVb8n8Mi+#rw7 z&4p4tkoksB?q@q=W7A*aHO3-hj2LnBkK=3>uR`on=k!}ivvx9;A>Ww-jl z-d5h2i32|$M8|w6>xbe(P_cqGozyiFFXZpovE$y|{a<7FRU;y*dcTy1guu~DI0EP8 z^*jp7NkI4&E^k!T$TKbOD~(96^ts;SJlK%Biu>5yEI!-KyY`(rK}0JKPPvponhGJE z)&g=FG+dRhHIzG^X5MLA6T=>|ifD|wkPn^euYYw1R@bGktR<9n56#ej7H-$-_T<|85DB zu(=wt35N*Jf}zW=tiwf<1KSE%z=E#=6eQO>g&3d7I+YGbN}#@Ju;DuYb5ZING)Vxe xCiM=O+W#x3*