From mboxrd@z Thu Jan 1 00:00:00 1970 From: Charles Sebold Subject: Re: org-plot and timestamps Date: Thu, 30 Oct 2008 10:35:43 -0500 Message-ID: References: <87prlm83pl.fsf@gmail.com> <87iqrb88qd.fsf@mitre.org> Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Return-path: Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1KvZYw-0000CK-2N for emacs-orgmode@gnu.org; Thu, 30 Oct 2008 11:35:54 -0400 Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1KvZYv-0000Bn-Bi for emacs-orgmode@gnu.org; Thu, 30 Oct 2008 11:35:53 -0400 Received: from [199.232.76.173] (port=56032 helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1KvZYv-0000BZ-3D for emacs-orgmode@gnu.org; Thu, 30 Oct 2008 11:35:53 -0400 Received: from yw-out-1718.google.com ([74.125.46.156]:21686) by monty-python.gnu.org with esmtp (Exim 4.60) (envelope-from ) id 1KvZYv-0000uJ-0b for emacs-orgmode@gnu.org; Thu, 30 Oct 2008 11:35:53 -0400 Received: by yw-out-1718.google.com with SMTP id 9so252445ywk.66 for ; Thu, 30 Oct 2008 08:35:49 -0700 (PDT) In-Reply-To: <87iqrb88qd.fsf@mitre.org> (Eric Schulte's message of "Tue\, 28 Oct 2008 09\:23\:53 -0700") List-Id: "General discussions about Org-mode." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: emacs-orgmode-bounces+geo-emacs-orgmode=m.gmane.org@gnu.org Errors-To: emacs-orgmode-bounces+geo-emacs-orgmode=m.gmane.org@gnu.org To: emacs-orgmode@gnu.org On 28 Oct 2008, Eric Schulte wrote: > Hi Charles, The patch looks great, I vote we drop it 'as is' into > org-plot.el. The only enhancement that comes to mind would be to > expose the `time-ind' variable as a plot option. Allowing users to > specify different time formats, but really if they're that > sophisticated in their use of gnuplot, then they can do that on their > own through the `set:' option. Thanks for the addition! -- Eric If I understand you correctly, then what we want to expose is the "timefmt" that is put into the data file and then passed to gnuplot. The following patch is a complete one against current which adds this (it works for me, at least), and documents the new +PLOT option behavior. The one thing I'm not sure about is my method of passing the timefmt parameter all the way into the temp file creation function. I made a buffer-local variable there to do it. That seemed the least intrusive way to accomplish this, but it seemed like poor practice. Thoughts? You know, I really ought to allow a person to customize this variable (I mean, using customize). ------------------------------------------------------------------------ Changes in origin/master Modified doc/org.texi diff --git a/doc/org.texi b/doc/org.texi index b675d92..60be4de 100644 --- a/doc/org.texi +++ b/doc/org.texi @@ -2345,6 +2345,10 @@ Specify an entire line to be inserted in the gnuplot script. When plotting @code{3d} or @code{grid} types, set this to @code{t} to graph a flat mapping rather than a @code{3d} slope. +@item timefmt +Specify format of org-mode timestamps as they will be parsed by gnuplot. +Defaults to '%Y-%m-%d-%H:%M:%S'. + @item script If you want total control you can specify a script file (place the file name between double quotes) which will be used to plot. Before plotting, every Modified lisp/org-plot.el diff --git a/lisp/org-plot.el b/lisp/org-plot.el index db67257..f69bfc6 100644 --- a/lisp/org-plot.el +++ b/lisp/org-plot.el @@ -51,17 +51,18 @@ Returns the resulting property list." (let (o) (when options - (let ((op '(("type" . :plot-type) - ("script" . :script) - ("line" . :line) - ("set" . :set) - ("title" . :title) - ("ind" . :ind) - ("deps" . :deps) - ("with" . :with) - ("file" . :file) - ("labels" . :labels) - ("map" . :map))) + (let ((op '(("type" . :plot-type) + ("script" . :script) + ("line" . :line) + ("set" . :set) + ("title" . :title) + ("ind" . :ind) + ("deps" . :deps) + ("with" . :with) + ("file" . :file) + ("labels" . :labels) + ("map" . :map) + ("timefmt" . :timefmt))) (multiples '("set" "line")) (regexp ":\\([\"][^\"]+?[\"]\\|[(][^)]+?[)]\\|[^ \t\n\r;,.]*\\)") (start 0) @@ -101,20 +102,31 @@ will be added. Returns the resulting property list." (org-plot/add-options-to-plist params (match-string 1 line)) params))) +(defun org-plot-quote-timestamp-field (s) + "Convert field S from timestamp to Unix time and export to gnuplot." + (format-time-string org-plot-timestamp-fmt (org-time-string-to-time s))) + (defun org-plot-quote-tsv-field (s) "Quote field S for export to gnuplot." (if (string-match org-table-number-regexp s) s - (concat "\"" (mapconcat 'identity (split-string s "\"") "\"\"") "\""))) + (if (string-match org-ts-regexp3 s) + (org-plot-quote-timestamp-field s) + (concat "\"" (mapconcat 'identity (split-string s "\"") "\"\"") "\"")))) (defun org-plot/gnuplot-to-data (table data-file params) "Export TABLE to DATA-FILE in a format readable by gnuplot. Pass PARAMS through to `orgtbl-to-generic' when exporting TABLE." (with-temp-file - data-file (insert (orgtbl-to-generic - table - (org-combine-plists - '(:sep "\t" :fmt org-plot-quote-tsv-field) - params)))) + data-file + (make-local-variable 'org-plot-timestamp-fmt) + (setq org-plot-timestamp-fmt (or + (plist-get params :timefmt) + "%Y-%m-%d-%H:%M:%S")) + (insert (orgtbl-to-generic + table + (org-combine-plists + '(:sep "\t" :fmt org-plot-quote-tsv-field) + params)))) nil) (defun org-plot/gnuplot-to-grid-data (table data-file params) @@ -180,6 +192,8 @@ NUM-COLS controls the number of columns plotted in a 2-d plot." (title (plist-get params :title)) (file (plist-get params :file)) (ind (plist-get params :ind)) + (time-ind (plist-get params :timeind)) + (timefmt (plist-get params :timefmt)) (text-ind (plist-get params :textind)) (deps (if (plist-member params :deps) (plist-get params :deps))) (col-labels (plist-get params :labels)) @@ -217,6 +231,11 @@ NUM-COLS controls the number of columns plotted in a 2-d plot." (mapconcat (lambda (pair) (format "\"%s\" %d" (cdr pair) (car pair))) y-labels ", ")))) + (when time-ind ;; timestamp index + (add-to-script "set xdata time") + (add-to-script (concat "set timefmt \"" + (or timefmt ;; timefmt passed to gnuplot + "%Y-%m-%d-%H:%M:%S") "\""))) (case type ;; plot command ('2d (dotimes (col num-cols) (unless (and (equal type '2d) @@ -284,16 +303,24 @@ line directly before or after the table." ('grid (let ((y-labels (org-plot/gnuplot-to-grid-data table data-file params))) (when y-labels (plist-put params :ylabels y-labels))))) - ;; check for text ind column + ;; check for timestamp ind column (let ((ind (- (plist-get params :ind) 1))) - (when (and (>= ind 0) (equal '2d (plist-get params :plot-type))) - (if (> (length - (delq 0 (mapcar + (when (and (>= ind 0) (equal '2d (plist-get params :plot-type))) + (if (= (length + (delq 0 (mapcar (lambda (el) - (if (string-match org-table-number-regexp el) + (if (string-match org-ts-regexp3 el) 0 1)) (mapcar (lambda (row) (nth ind row)) table)))) 0) - (plist-put params :textind t)))) + (plist-put params :timeind t) + ;; check for text ind column + (if (> (length + (delq 0 (mapcar + (lambda (el) + (if (string-match org-table-number-regexp el) + 0 1)) + (mapcar (lambda (row) (nth ind row)) table)))) 0) + (plist-put params :textind t))))) ;; write script (with-temp-buffer (if (plist-get params :script) ;; user script @@ -307,7 +334,8 @@ line directly before or after the table." (gnuplot-mode) (gnuplot-send-buffer-to-gnuplot)) ;; cleanup - (bury-buffer (get-buffer "*gnuplot*"))(delete-file data-file)))) + (bury-buffer (get-buffer "*gnuplot*")) + (delete-file data-file)))) (provide 'org-plot) -- Charles Sebold http://merbc.invigorated.org/ http://triablogue.blogspot.com/