aboutsummaryrefslogtreecommitdiffstats
path: root/lisp/org/org-plot.el
diff options
context:
space:
mode:
authorRasmus2017-06-21 13:20:20 +0200
committerRasmus2017-06-22 11:54:18 +0200
commit5cecd275820df825c51bf9a27fcc7e35f30ff273 (patch)
treeb3f72e63953613d565e6d5a35bec97f158eb603c /lisp/org/org-plot.el
parent386a3da920482b8cb3e962fb944d135c8a770e26 (diff)
downloademacs-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.el233
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.
51Returns the resulting property list." 51Returns 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."
119Pass PARAMS through to `orgtbl-to-generic' when exporting TABLE." 117Pass 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.
187Optional argument PREFACE returns only option parameters in a 184Optional argument PREFACE returns only option parameters in a
188manner suitable for prepending to a user-specified script." 185manner 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