diff options
| author | Rasmus | 2017-06-21 13:20:20 +0200 |
|---|---|---|
| committer | Rasmus | 2017-06-22 11:54:18 +0200 |
| commit | 5cecd275820df825c51bf9a27fcc7e35f30ff273 (patch) | |
| tree | b3f72e63953613d565e6d5a35bec97f158eb603c /lisp/org/org-plot.el | |
| parent | 386a3da920482b8cb3e962fb944d135c8a770e26 (diff) | |
| download | emacs-5cecd275820df825c51bf9a27fcc7e35f30ff273.tar.gz emacs-5cecd275820df825c51bf9a27fcc7e35f30ff273.zip | |
Update Org to v9.0.9
Please see etc/ORG-NEWS for details.
Diffstat (limited to 'lisp/org/org-plot.el')
| -rw-r--r-- | lisp/org/org-plot.el | 233 |
1 files changed, 115 insertions, 118 deletions
diff --git a/lisp/org/org-plot.el b/lisp/org/org-plot.el index 5ccfbb1e662..449143a47af 100644 --- a/lisp/org/org-plot.el +++ b/lisp/org/org-plot.el | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | ;;; org-plot.el --- Support for plotting from Org-mode | 1 | ;;; org-plot.el --- Support for Plotting from Org -*- lexical-binding: t; -*- |
| 2 | 2 | ||
| 3 | ;; Copyright (C) 2008-2017 Free Software Foundation, Inc. | 3 | ;; Copyright (C) 2008-2017 Free Software Foundation, Inc. |
| 4 | ;; | 4 | ;; |
| @@ -25,14 +25,14 @@ | |||
| 25 | 25 | ||
| 26 | ;; Borrows ideas and a couple of lines of code from org-exp.el. | 26 | ;; Borrows ideas and a couple of lines of code from org-exp.el. |
| 27 | 27 | ||
| 28 | ;; Thanks to the org-mode mailing list for testing and implementation | 28 | ;; Thanks to the Org mailing list for testing and implementation and |
| 29 | ;; and feature suggestions | 29 | ;; feature suggestions |
| 30 | 30 | ||
| 31 | ;;; Code: | 31 | ;;; Code: |
| 32 | |||
| 33 | (require 'cl-lib) | ||
| 32 | (require 'org) | 34 | (require 'org) |
| 33 | (require 'org-table) | 35 | (require 'org-table) |
| 34 | (eval-when-compile | ||
| 35 | (require 'cl)) | ||
| 36 | 36 | ||
| 37 | (declare-function gnuplot-delchar-or-maybe-eof "ext:gnuplot" (arg)) | 37 | (declare-function gnuplot-delchar-or-maybe-eof "ext:gnuplot" (arg)) |
| 38 | (declare-function gnuplot-mode "ext:gnuplot" ()) | 38 | (declare-function gnuplot-mode "ext:gnuplot" ()) |
| @@ -49,41 +49,39 @@ | |||
| 49 | (defun org-plot/add-options-to-plist (p options) | 49 | (defun org-plot/add-options-to-plist (p options) |
| 50 | "Parse an OPTIONS line and set values in the property list P. | 50 | "Parse an OPTIONS line and set values in the property list P. |
| 51 | Returns the resulting property list." | 51 | Returns the resulting property list." |
| 52 | (let (o) | 52 | (when options |
| 53 | (when options | 53 | (let ((op '(("type" . :plot-type) |
| 54 | (let ((op '(("type" . :plot-type) | 54 | ("script" . :script) |
| 55 | ("script" . :script) | 55 | ("line" . :line) |
| 56 | ("line" . :line) | 56 | ("set" . :set) |
| 57 | ("set" . :set) | 57 | ("title" . :title) |
| 58 | ("title" . :title) | 58 | ("ind" . :ind) |
| 59 | ("ind" . :ind) | 59 | ("deps" . :deps) |
| 60 | ("deps" . :deps) | 60 | ("with" . :with) |
| 61 | ("with" . :with) | 61 | ("file" . :file) |
| 62 | ("file" . :file) | 62 | ("labels" . :labels) |
| 63 | ("labels" . :labels) | 63 | ("map" . :map) |
| 64 | ("map" . :map) | 64 | ("timeind" . :timeind) |
| 65 | ("timeind" . :timeind) | 65 | ("timefmt" . :timefmt))) |
| 66 | ("timefmt" . :timefmt))) | 66 | (multiples '("set" "line")) |
| 67 | (multiples '("set" "line")) | 67 | (regexp ":\\([\"][^\"]+?[\"]\\|[(][^)]+?[)]\\|[^ \t\n\r;,.]*\\)") |
| 68 | (regexp ":\\([\"][^\"]+?[\"]\\|[(][^)]+?[)]\\|[^ \t\n\r;,.]*\\)") | 68 | (start 0)) |
| 69 | (start 0) | 69 | (dolist (o op) |
| 70 | o) | 70 | (if (member (car o) multiples) ;; keys with multiple values |
| 71 | (while (setq o (pop op)) | 71 | (while (string-match |
| 72 | (if (member (car o) multiples) ;; keys with multiple values | 72 | (concat (regexp-quote (car o)) regexp) |
| 73 | (while (string-match | 73 | options start) |
| 74 | (concat (regexp-quote (car o)) regexp) | 74 | (setq start (match-end 0)) |
| 75 | options start) | 75 | (setq p (plist-put p (cdr o) |
| 76 | (setq start (match-end 0)) | 76 | (cons (car (read-from-string |
| 77 | (setq p (plist-put p (cdr o) | 77 | (match-string 1 options))) |
| 78 | (cons (car (read-from-string | 78 | (plist-get p (cdr o))))) |
| 79 | (match-string 1 options))) | 79 | p) |
| 80 | (plist-get p (cdr o))))) | 80 | (if (string-match (concat (regexp-quote (car o)) regexp) |
| 81 | p) | 81 | options) |
| 82 | (if (string-match (concat (regexp-quote (car o)) regexp) | 82 | (setq p (plist-put p (cdr o) |
| 83 | options) | 83 | (car (read-from-string |
| 84 | (setq p (plist-put p (cdr o) | 84 | (match-string 1 options)))))))))) |
| 85 | (car (read-from-string | ||
| 86 | (match-string 1 options))))))))))) | ||
| 87 | p) | 85 | p) |
| 88 | 86 | ||
| 89 | (defun org-plot/goto-nearest-table () | 87 | (defun org-plot/goto-nearest-table () |
| @@ -119,10 +117,9 @@ will be added. Returns the resulting property list." | |||
| 119 | Pass PARAMS through to `orgtbl-to-generic' when exporting TABLE." | 117 | Pass PARAMS through to `orgtbl-to-generic' when exporting TABLE." |
| 120 | (with-temp-file | 118 | (with-temp-file |
| 121 | data-file | 119 | data-file |
| 122 | (make-local-variable 'org-plot-timestamp-fmt) | 120 | (setq-local org-plot-timestamp-fmt (or |
| 123 | (setq org-plot-timestamp-fmt (or | 121 | (plist-get params :timefmt) |
| 124 | (plist-get params :timefmt) | 122 | "%Y-%m-%d-%H:%M:%S")) |
| 125 | "%Y-%m-%d-%H:%M:%S")) | ||
| 126 | (insert (orgtbl-to-generic | 123 | (insert (orgtbl-to-generic |
| 127 | table | 124 | table |
| 128 | (org-combine-plists | 125 | (org-combine-plists |
| @@ -140,7 +137,7 @@ and dependant variables." | |||
| 140 | (deps (if (plist-member params :deps) | 137 | (deps (if (plist-member params :deps) |
| 141 | (mapcar (lambda (val) (- val 1)) (plist-get params :deps)) | 138 | (mapcar (lambda (val) (- val 1)) (plist-get params :deps)) |
| 142 | (let (collector) | 139 | (let (collector) |
| 143 | (dotimes (col (length (first table))) | 140 | (dotimes (col (length (nth 0 table))) |
| 144 | (setf collector (cons col collector))) | 141 | (setf collector (cons col collector))) |
| 145 | collector))) | 142 | collector))) |
| 146 | (counter 0) | 143 | (counter 0) |
| @@ -158,7 +155,7 @@ and dependant variables." | |||
| 158 | table))) | 155 | table))) |
| 159 | ;; write table to gnuplot grid datafile format | 156 | ;; write table to gnuplot grid datafile format |
| 160 | (with-temp-file data-file | 157 | (with-temp-file data-file |
| 161 | (let ((num-rows (length table)) (num-cols (length (first table))) | 158 | (let ((num-rows (length table)) (num-cols (length (nth 0 table))) |
| 162 | (gnuplot-row (lambda (col row value) | 159 | (gnuplot-row (lambda (col row value) |
| 163 | (setf col (+ 1 col)) (setf row (+ 1 row)) | 160 | (setf col (+ 1 col)) (setf row (+ 1 row)) |
| 164 | (format "%f %f %f\n%f %f %f\n" | 161 | (format "%f %f %f\n%f %f %f\n" |
| @@ -187,9 +184,7 @@ NUM-COLS controls the number of columns plotted in a 2-d plot. | |||
| 187 | Optional argument PREFACE returns only option parameters in a | 184 | Optional argument PREFACE returns only option parameters in a |
| 188 | manner suitable for prepending to a user-specified script." | 185 | manner suitable for prepending to a user-specified script." |
| 189 | (let* ((type (plist-get params :plot-type)) | 186 | (let* ((type (plist-get params :plot-type)) |
| 190 | (with (if (equal type 'grid) | 187 | (with (if (eq type 'grid) 'pm3d (plist-get params :with))) |
| 191 | 'pm3d | ||
| 192 | (plist-get params :with))) | ||
| 193 | (sets (plist-get params :set)) | 188 | (sets (plist-get params :set)) |
| 194 | (lines (plist-get params :line)) | 189 | (lines (plist-get params :line)) |
| 195 | (map (plist-get params :map)) | 190 | (map (plist-get params :map)) |
| @@ -204,68 +199,72 @@ manner suitable for prepending to a user-specified script." | |||
| 204 | (x-labels (plist-get params :xlabels)) | 199 | (x-labels (plist-get params :xlabels)) |
| 205 | (y-labels (plist-get params :ylabels)) | 200 | (y-labels (plist-get params :ylabels)) |
| 206 | (plot-str "'%s' using %s%d%s with %s title '%s'") | 201 | (plot-str "'%s' using %s%d%s with %s title '%s'") |
| 207 | (plot-cmd (case type | 202 | (plot-cmd (pcase type |
| 208 | ('2d "plot") | 203 | (`2d "plot") |
| 209 | ('3d "splot") | 204 | (`3d "splot") |
| 210 | ('grid "splot"))) | 205 | (`grid "splot"))) |
| 211 | (script "reset") | 206 | (script "reset") |
| 212 | ; ats = add-to-script | 207 | ;; ats = add-to-script |
| 213 | (ats (lambda (line) (setf script (format "%s\n%s" script line)))) | 208 | (ats (lambda (line) (setf script (concat script "\n" line)))) |
| 214 | plot-lines) | 209 | plot-lines) |
| 215 | (when file ;; output file | 210 | (when file ; output file |
| 216 | (funcall ats (format "set term %s" (file-name-extension file))) | 211 | (funcall ats (format "set term %s" (file-name-extension file))) |
| 217 | (funcall ats (format "set output '%s'" file))) | 212 | (funcall ats (format "set output '%s'" file))) |
| 218 | (case type ;; type | 213 | (pcase type ; type |
| 219 | ('2d ()) | 214 | (`2d ()) |
| 220 | ('3d (if map (funcall ats "set map"))) | 215 | (`3d (when map (funcall ats "set map"))) |
| 221 | ('grid (if map (funcall ats "set pm3d map") | 216 | (`grid (funcall ats (if map "set pm3d map" "set pm3d")))) |
| 222 | (funcall ats "set pm3d")))) | 217 | (when title (funcall ats (format "set title '%s'" title))) ; title |
| 223 | (when title (funcall ats (format "set title '%s'" title))) ;; title | 218 | (mapc ats lines) ; line |
| 224 | (when lines (mapc (lambda (el) (funcall ats el)) lines)) ;; line | 219 | (dolist (el sets) (funcall ats (format "set %s" el))) ; set |
| 225 | (when sets ;; set | 220 | ;; Unless specified otherwise, values are TAB separated. |
| 226 | (mapc (lambda (el) (funcall ats (format "set %s" el))) sets)) | 221 | (unless (string-match-p "^set datafile separator" script) |
| 227 | (when x-labels ;; x labels (xtics) | 222 | (funcall ats "set datafile separator \"\\t\"")) |
| 223 | (when x-labels ; x labels (xtics) | ||
| 228 | (funcall ats | 224 | (funcall ats |
| 229 | (format "set xtics (%s)" | 225 | (format "set xtics (%s)" |
| 230 | (mapconcat (lambda (pair) | 226 | (mapconcat (lambda (pair) |
| 231 | (format "\"%s\" %d" (cdr pair) (car pair))) | 227 | (format "\"%s\" %d" (cdr pair) (car pair))) |
| 232 | x-labels ", ")))) | 228 | x-labels ", ")))) |
| 233 | (when y-labels ;; y labels (ytics) | 229 | (when y-labels ; y labels (ytics) |
| 234 | (funcall ats | 230 | (funcall ats |
| 235 | (format "set ytics (%s)" | 231 | (format "set ytics (%s)" |
| 236 | (mapconcat (lambda (pair) | 232 | (mapconcat (lambda (pair) |
| 237 | (format "\"%s\" %d" (cdr pair) (car pair))) | 233 | (format "\"%s\" %d" (cdr pair) (car pair))) |
| 238 | y-labels ", ")))) | 234 | y-labels ", ")))) |
| 239 | (when time-ind ;; timestamp index | 235 | (when time-ind ; timestamp index |
| 240 | (funcall ats "set xdata time") | 236 | (funcall ats "set xdata time") |
| 241 | (funcall ats (concat "set timefmt \"" | 237 | (funcall ats (concat "set timefmt \"" |
| 242 | (or timefmt ;; timefmt passed to gnuplot | 238 | (or timefmt ; timefmt passed to gnuplot |
| 243 | "%Y-%m-%d-%H:%M:%S") "\""))) | 239 | "%Y-%m-%d-%H:%M:%S") "\""))) |
| 244 | (unless preface | 240 | (unless preface |
| 245 | (case type ;; plot command | 241 | (pcase type ; plot command |
| 246 | ('2d (dotimes (col num-cols) | 242 | (`2d (dotimes (col num-cols) |
| 247 | (unless (and (equal type '2d) | 243 | (unless (and (eq type '2d) |
| 248 | (or (and ind (equal (+ 1 col) ind)) | 244 | (or (and ind (equal (1+ col) ind)) |
| 249 | (and deps (not (member (+ 1 col) deps))))) | 245 | (and deps (not (member (1+ col) deps))))) |
| 250 | (setf plot-lines | 246 | (setf plot-lines |
| 251 | (cons | 247 | (cons |
| 252 | (format plot-str data-file | 248 | (format plot-str data-file |
| 253 | (or (and ind (> ind 0) | 249 | (or (and ind (> ind 0) |
| 254 | (not text-ind) | 250 | (not text-ind) |
| 255 | (format "%d:" ind)) "") | 251 | (format "%d:" ind)) "") |
| 256 | (+ 1 col) | 252 | (1+ col) |
| 257 | (if text-ind (format ":xticlabel(%d)" ind) "") | 253 | (if text-ind (format ":xticlabel(%d)" ind) "") |
| 258 | with | 254 | with |
| 259 | (or (nth col col-labels) (format "%d" (+ 1 col)))) | 255 | (or (nth col col-labels) |
| 256 | (format "%d" (1+ col)))) | ||
| 260 | plot-lines))))) | 257 | plot-lines))))) |
| 261 | ('3d | 258 | (`3d |
| 262 | (setq plot-lines (list (format "'%s' matrix with %s title ''" | 259 | (setq plot-lines (list (format "'%s' matrix with %s title ''" |
| 263 | data-file with)))) | 260 | data-file with)))) |
| 264 | ('grid | 261 | (`grid |
| 265 | (setq plot-lines (list (format "'%s' with %s title ''" | 262 | (setq plot-lines (list (format "'%s' with %s title ''" |
| 266 | data-file with))))) | 263 | data-file with))))) |
| 267 | (funcall ats | 264 | (funcall ats |
| 268 | (concat plot-cmd " " (mapconcat 'identity (reverse plot-lines) ",\\\n ")))) | 265 | (concat plot-cmd " " (mapconcat #'identity |
| 266 | (reverse plot-lines) | ||
| 267 | ",\\\n ")))) | ||
| 269 | script)) | 268 | script)) |
| 270 | 269 | ||
| 271 | ;;----------------------------------------------------------------------------- | 270 | ;;----------------------------------------------------------------------------- |
| @@ -279,59 +278,59 @@ line directly before or after the table." | |||
| 279 | (require 'gnuplot) | 278 | (require 'gnuplot) |
| 280 | (save-window-excursion | 279 | (save-window-excursion |
| 281 | (delete-other-windows) | 280 | (delete-other-windows) |
| 282 | (when (get-buffer "*gnuplot*") ;; reset *gnuplot* if it already running | 281 | (when (get-buffer "*gnuplot*") ; reset *gnuplot* if it already running |
| 283 | (with-current-buffer "*gnuplot*" | 282 | (with-current-buffer "*gnuplot*" |
| 284 | (goto-char (point-max)) | 283 | (goto-char (point-max)))) |
| 285 | (gnuplot-delchar-or-maybe-eof nil))) | ||
| 286 | (org-plot/goto-nearest-table) | 284 | (org-plot/goto-nearest-table) |
| 287 | ;; set default options | 285 | ;; Set default options. |
| 288 | (mapc | 286 | (dolist (pair org-plot/gnuplot-default-options) |
| 289 | (lambda (pair) | 287 | (unless (plist-member params (car pair)) |
| 290 | (unless (plist-member params (car pair)) | 288 | (setf params (plist-put params (car pair) (cdr pair))))) |
| 291 | (setf params (plist-put params (car pair) (cdr pair))))) | ||
| 292 | org-plot/gnuplot-default-options) | ||
| 293 | ;; collect table and table information | 289 | ;; collect table and table information |
| 294 | (let* ((data-file (make-temp-file "org-plot")) | 290 | (let* ((data-file (make-temp-file "org-plot")) |
| 295 | (table (org-table-to-lisp)) | 291 | (table (org-table-to-lisp)) |
| 296 | (num-cols (length (if (eq (first table) 'hline) (second table) | 292 | (num-cols (length (if (eq (nth 0 table) 'hline) (nth 1 table) |
| 297 | (first table))))) | 293 | (nth 0 table))))) |
| 298 | (while (equal 'hline (first table)) (setf table (cdr table))) | 294 | (run-with-idle-timer 0.1 nil #'delete-file data-file) |
| 299 | (when (equal (second table) 'hline) | 295 | (while (eq 'hline (car table)) (setf table (cdr table))) |
| 300 | (setf params (plist-put params :labels (first table))) ;; headers to labels | 296 | (when (eq (cadr table) 'hline) |
| 301 | (setf table (delq 'hline (cdr table)))) ;; clean non-data from table | 297 | (setf params |
| 302 | ;; collect options | 298 | (plist-put params :labels (nth 0 table))) ; headers to labels |
| 299 | (setf table (delq 'hline (cdr table)))) ; clean non-data from table | ||
| 300 | ;; Collect options. | ||
| 303 | (save-excursion (while (and (equal 0 (forward-line -1)) | 301 | (save-excursion (while (and (equal 0 (forward-line -1)) |
| 304 | (looking-at "[[:space:]]*#\\+")) | 302 | (looking-at "[[:space:]]*#\\+")) |
| 305 | (setf params (org-plot/collect-options params)))) | 303 | (setf params (org-plot/collect-options params)))) |
| 306 | ;; dump table to datafile (very different for grid) | 304 | ;; Dump table to datafile (very different for grid). |
| 307 | (case (plist-get params :plot-type) | 305 | (pcase (plist-get params :plot-type) |
| 308 | ('2d (org-plot/gnuplot-to-data table data-file params)) | 306 | (`2d (org-plot/gnuplot-to-data table data-file params)) |
| 309 | ('3d (org-plot/gnuplot-to-data table data-file params)) | 307 | (`3d (org-plot/gnuplot-to-data table data-file params)) |
| 310 | ('grid (let ((y-labels (org-plot/gnuplot-to-grid-data | 308 | (`grid (let ((y-labels (org-plot/gnuplot-to-grid-data |
| 311 | table data-file params))) | 309 | table data-file params))) |
| 312 | (when y-labels (plist-put params :ylabels y-labels))))) | 310 | (when y-labels (plist-put params :ylabels y-labels))))) |
| 313 | ;; check for timestamp ind column | 311 | ;; Check for timestamp ind column. |
| 314 | (let ((ind (- (plist-get params :ind) 1))) | 312 | (let ((ind (1- (plist-get params :ind)))) |
| 315 | (when (and (>= ind 0) (equal '2d (plist-get params :plot-type))) | 313 | (when (and (>= ind 0) (eq '2d (plist-get params :plot-type))) |
| 316 | (if (= (length | 314 | (if (= (length |
| 317 | (delq 0 (mapcar | 315 | (delq 0 (mapcar |
| 318 | (lambda (el) | 316 | (lambda (el) |
| 319 | (if (string-match org-ts-regexp3 el) | 317 | (if (string-match org-ts-regexp3 el) 0 1)) |
| 320 | 0 1)) | 318 | (mapcar (lambda (row) (nth ind row)) table)))) |
| 321 | (mapcar (lambda (row) (nth ind row)) table)))) 0) | 319 | 0) |
| 322 | (plist-put params :timeind t) | 320 | (plist-put params :timeind t) |
| 323 | ;; check for text ind column | 321 | ;; Check for text ind column. |
| 324 | (if (or (string= (plist-get params :with) "hist") | 322 | (if (or (string= (plist-get params :with) "hist") |
| 325 | (> (length | 323 | (> (length |
| 326 | (delq 0 (mapcar | 324 | (delq 0 (mapcar |
| 327 | (lambda (el) | 325 | (lambda (el) |
| 328 | (if (string-match org-table-number-regexp el) | 326 | (if (string-match org-table-number-regexp el) |
| 329 | 0 1)) | 327 | 0 1)) |
| 330 | (mapcar (lambda (row) (nth ind row)) table)))) 0)) | 328 | (mapcar (lambda (row) (nth ind row)) table)))) |
| 329 | 0)) | ||
| 331 | (plist-put params :textind t))))) | 330 | (plist-put params :textind t))))) |
| 332 | ;; write script | 331 | ;; Write script. |
| 333 | (with-temp-buffer | 332 | (with-temp-buffer |
| 334 | (if (plist-get params :script) ;; user script | 333 | (if (plist-get params :script) ; user script |
| 335 | (progn (insert | 334 | (progn (insert |
| 336 | (org-plot/gnuplot-script data-file num-cols params t)) | 335 | (org-plot/gnuplot-script data-file num-cols params t)) |
| 337 | (insert "\n") | 336 | (insert "\n") |
| @@ -339,14 +338,12 @@ line directly before or after the table." | |||
| 339 | (goto-char (point-min)) | 338 | (goto-char (point-min)) |
| 340 | (while (re-search-forward "$datafile" nil t) | 339 | (while (re-search-forward "$datafile" nil t) |
| 341 | (replace-match data-file nil nil))) | 340 | (replace-match data-file nil nil))) |
| 342 | (insert | 341 | (insert (org-plot/gnuplot-script data-file num-cols params))) |
| 343 | (org-plot/gnuplot-script data-file num-cols params))) | 342 | ;; Graph table. |
| 344 | ;; graph table | ||
| 345 | (gnuplot-mode) | 343 | (gnuplot-mode) |
| 346 | (gnuplot-send-buffer-to-gnuplot)) | 344 | (gnuplot-send-buffer-to-gnuplot)) |
| 347 | ;; cleanup | 345 | ;; Cleanup. |
| 348 | (bury-buffer (get-buffer "*gnuplot*")) | 346 | (bury-buffer (get-buffer "*gnuplot*"))))) |
| 349 | (run-with-idle-timer 0.1 nil (lambda () (delete-file data-file)))))) | ||
| 350 | 347 | ||
| 351 | (provide 'org-plot) | 348 | (provide 'org-plot) |
| 352 | 349 | ||