[CM] Pest Question?

Torsten Anders Torsten.Anders at hfm.uni-weimar.de
Wed Jun 12 13:35:28 PDT 2002


> > Is there any kind of timeline on a "plotter like thing running in Linux" 
> > ?? Thanks,

Dear Ken,

For my own needs I wrote a small interface to gnuplot for that purpose. Its 
of course less good looking than the CM plotter, but it plots value lists in 
2D and 3D and supports various settings of gnuplot. And it is small enough 
that you may easily extend it for your porpose...

The program is attached.

Kind regards,
Torsten

PS: BTW, I did some more stuff using CM for my music, e.g., an interface and 
higher abstractions to the tao physical modelling sound synthesis program, 
envelopes expressed as numeric functions plus a set of functions to generate, 
combine and transform them etc. Any interest? Then I need to find some web 
space -- I still do not have a home page...

 

If there is some interest I 


-------------- next part --------------
;;; The function 'plot' is an interface to gnuplot.
;;; Very little error checking...
;;; copyright 2002 by Torsten Anders
;;; anders at uni-weimar.de

#| ; tests

(plot '(0 5 3 4))			; simple plot 
(plot '(1 2 3 4) :style :impulses)	; line style 
(plot '(1 2 3 4) :x '(0.1 0.5 2 2.1))	; x and y given
(plot '(1 2 3 4)			; 3D plot
      :x '(0.1 0.5 2 2.1)
      :z '(0.5 3 2 -1)
      :style :linespoints)
(plot '((1 5 3) (4 6 0)))		; multiple plots
(plot '((1 5 3) (4 6 0))		; multiple line styles
      :style '(:lines :linespoints)) 
(plot '((1 5 3) (4 6 0))		; multiple 3D plots
      :x '((1 2 1.5) (1 7 6))
      :z '((0 1 4) (0 3 2)))
(plot '(0 5 3 4)			; additional settings
      :set '("title 'test'"
	     "output '/home/to/plot.ps'"
	     "terminal postscript"))
|#

(defun plot (y &key x z
	       (style :linespoints) smooth?
	       set
	       (data-file "/tmp/gnuplot_daten")
	       (command-file "/tmp/gnuplot_command"))
  "Generates script and data file for gnuplot and calls gnuplot with these files.
Coordinates (i.e. x, y, and z) may be either a list of numbers (for a single plot) or a list of lists (for multiple plots) -- the nesting should be the same. Specifying z results in a 3D plot. The style option (sets the lines style) expects either a single keyword for all or a list of styles with a new value for every plot. All styles allowed by gnuplot are valid as keyword. set expects a list of strings describing arbitrary additional settings to gnuplot (without the leading 'set').
data-file gives the beginning of the data file names (every plot is written to an own data file). command-file is the name of the command file."
  (let* ((plot-cmd (if z "splot" "plot")) ; 2D or 3D ?
	 (data-files   ; write-string-to-file returns filename
	  (loop for d in (combine-coordinates x y z)
		for i from 1
		collect (write-string-to-file
			 (make-lines d)
			 (format nil "~a~a" data-file i))))
	 (plots	       ; file name for data and style as strings
	  (mapcar #'(lambda (d s)
		      (format NIL " '~a' with ~a" d s))
		  data-files
		  (if (listp style)
		      (mapcar #'(lambda (s) (string-downcase (string s)))
			      style)
		      (make-list (length data-files)
				 :initial-element
				 (string-downcase (string style))))))
	 (settings (format NIL "~{set ~a~%~}" set)))
    (write-string-to-file
     (format nil "~a~a ~a ~{, ~a~} ; pause -1 'Hit return to continue' ~%"
	     settings
	     plot-cmd
	     (first plots)	; to put commata at correct position
	     (rest plots))
     command-file))
  (shell (format nil "xterm -e gnuplot ~a &" command-file)))


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; utils
;;;

(defun make-lines (data)
  "Writes each sublist of data in an own line"
  (format NIL "~{~{~,7F ~}~%~}" data))

; (make-lines '((0 1) (0.2 2) (1 3) (5 4)))

(defun combine-coordinates (x y z)
  "Combines the lists of x (and possibly y and z) coordinates into a list of the form (((x1 y1 z1) ...) [(<coors for second plot>) ...]). Both x or z may be NIL."
  (when (and z (or (not x) (not y)))
    (error "z can not be given without x or y."))
  (flet ((prepare (x y z) (remove NIL (list x y z))))
  (if (listp (first y))			; checks only first element !!
      (apply #'mapcar #'(lambda (xx &optional yy zz)
			  ;(print (list xx yy zz))
			  (util::mat-trans (prepare xx yy zz)))
	     (prepare x y z))
    (list (util::mat-trans (prepare x y z))))))

; (combine-coordinates '(1 2 3) NIL NIL)
; (combine-coordinates '(1 2 3) '(a b c) NIL)
; (combine-coordinates '((1 2 3) (5 6 7)) '((a b c) (x y z)) NIL)

(defun write-string-to-file (string out-file)
  "Writes (or overwrites) string into out-file and returns out-file."
  (with-open-file (out-stream out-file
		   :direction :output
		   :if-exists :supersede)
     (format out-stream string))
  out-file)

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; quote

;;; modified version of 'shell' in CM1 by Heinrich Taube
;;; for support of other Lisp platforms see "impl.lisp" 
#+CMU
(defun shell (string &key (wait T) (output T))
  "'Evaluates' string in /bin/sh and outputs result on *standard-output*. Start a child process and does not wait until process is finished. Therefore output of process may be mixed in outputs of other programm..."
  (unwind-protect 
      (let* ((process  (ext:run-program "/bin/sh" (list "-c" string)
					:output output
					:wait wait)))
	(ext:process-close process)
	process)))


More information about the Cmdist mailing list