#!/usr/bin/ruby # ************************************************************************** # eplot # Written by Christian Wolf # # eplot ("easy gnuplot") is a shell script which allows to pipe data easily # through gnuplot and create plots quickly, which can be saved in postscript, # PDF, PNG or EMF files. Plotting of multiple files into a single diagram is # supported. # ************************************************************************** # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the # Free Software Foundation, Inc., # 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # ************************************************************************** # Changelog: # 2.08 24.07.2017: -added dumb terminal support by Peter Barnes # 2.07 03.05.2007: -bugfix case where input file is empty # 2.06 09.12.2005: -bugfix style not set when single plot from stdin # 2.05 19.11.2005: -no dummy titles are displayed (tmp files etc.); bugfixes # 2.04 13.11.2005: -Added -o option: specify the name of the output file # 2.03 25.10.2005: -Bugfix: added some exception handling (File stuff) # 2.02 25.10.2005: -Added -D option (dump created files) # -Bugfix files containing dashes # 2.01 22.10.2005: -Enabled color for postscript & PDF output # -Changed option -w to option -l # -Added -w option to change line width # -Added -I option to change the order of style indices # -Added -B option to create vertical bars # 2.00 13.10.2005: -Port to the ruby programming language # 1.07 27.09.2005: -Bugfix removed meaningless error message in some cases # 1.06 03.07.2005: -Added -S: plotting multiple curves from a single column, # the curves being separated by blank lines. # -Fixed bug in the syntax validation code. # 1.05 01.07.2005: -Fixed compatibility issue with older versions of gnuplot. # -Fixed bug when options "-p -M" are provided # -Added some argument checking # 1.04 30.06.2005: -Bugfix option -M when data is piped # -Improved -t option to make multiple titles possible # 1.0 ??.??.2002: -Start of project, initial version written in # UNIX korn shell # ************************************************************************** require 'tempfile' # ************************************************************************** # CONFIGURATION $Version="2.07 03.05.2007" $TextViewer="cat" $GnuPlot4OrNewer=true # ************************************************************************** # VARIOUS CONSTANTS $err="eplot: *** ERROR *** " $barStyleIndex="20" $help=< Specify the output filename -d --dumb Output to dumb terminal (ascii art) Output formatting options: -r set the range of x and y axis values (e.g. -r [5:10][0:100]). -R set the aspect ratio (1 for a square shaped diagram) -s set the size factor -l set the type of curve (lines,points,linespoints,...) -w set the line width (default: 1) -x provide x-axis options --xlog log x-axis -y provide y-axis options --ylog log y-axis -t set the title(s) of the curve(s) (separated by @) -I set the order of the line styles (separated by ,) (e.g. -I "2,1,3,4,5") Miscellaneous opions: -B , creates vertical bars (separated by @) e.g. -B 100,0.8@200,0.8 -D --dump dump all used files as "eplot-dump-.dat" -O --open Immediately open output file -h --help print this help message -v --version print version information MARKER_MESSAGE $licence=<1 c=c+"empty-notitle" end @oc["TitleString"]=c end end # -------------------------------------------------------------------------- # ---- run multiple plots from multiple files # ---- argument: list of already opened files def runMulFrMulOpenedFiles(openedFiles) titleArr=nil titleArr=@oc["TitleString"].split("@") if @oc["TitleString"]!="" styleArr=@oc["StyleIndices"].split(",") # ---- eventually create vertical bars, which are # ---- nothing else than custom made data files if @oc["Bars"] != "" # ---- If no titles are requested, then we create # ---- a dummy title array if titleArr==nil titleArr=[] (1..openedFiles.length).each { |i| titleArr.push("default-title") } end barArr=@oc["Bars"].split("@") barArr.each do |b| # ---- Parse the bar coordinates bd=b.split(",") if bd.length!=2 $stderr.printf "%ssyntax error in option -B or --bar!\n",$err exit 1 end # ---- Create the file and add it to the list of files tmpf=Tempfile.new("eplot") tmpf.printf "%s %s",bd[0],bd[1] tmpf.flush openedFiles.push(tmpf) # ---- Create the entries in the title array len=openedFiles.length if titleArr if titleArr.length1 com=com+"\""+f.path+"\" " # ---- do we have a title? if titleArr if i>titleArr.length $stderr.printf "%syou need to specify a title for each curve!\n",$err exit 1 end case titleArr[i-1] when "bar-notitle" com=com+"notitle " when "empty-notitle" com=com+"notitle " when "default-title" ; else com=com+"title \""+titleArr[i-1]+"\" " end end if titleArr!=nil and titleArr[i-1]=="bar-notitle" com=com+"with impulses ls "+$barStyleIndex else com=com+"with "+@oc["LineType"]+" ls "+styleArr[i-1] end i=i+1 end plot(com,true) end # -------------------------------------------------------------------------- # ---- run multiple plots from multiple files # ---- argument: list of filenames def runMulFrMul(filenames) openedFiles=[] filenames.each do |fn| if not FileTest.exist?(fn) $stderr.printf "%scannot open file '%s' for reading.\n",$err,fn exit 1 end t=File.open(fn) openedFiles.push(t) end runMulFrMulOpenedFiles(openedFiles) openedFiles.each { |f| f.close } end # -------------------------------------------------------------------------- # ---- run multiple plots from a single file def runMulFrSin(filename) nocols=0 # ---- Let's see how many columns we have in the file File.open(filename) { |x| nocols=x.gets.split(" ").length } $stderr.printf "Found %d columns\n",nocols # ---- Traverse the columns and put them into seperate files files=[] for i in (1..nocols) tmpf=Tempfile.new("eplot") files.push(tmpf) extractColumn(filename,i,tmpf) end # ---- Call it as if we had multiple files removeDummyTitles(files.length) runMulFrMulOpenedFiles(files) files.each { |f| f.close } end # -------------------------------------------------------------------------- # ---- run multiple plots from a single file # ---- one single column, curves are separated by blank lines def runMulFrSeq(filename) files=[] begin file = File.open(filename) rescue $stderr.printf "%scannot open file '%s' for reading!\n",$err,filename exit 1 end startNewFile=true oldFile=tmpf=nil while line=file.gets # ---- only whitespace in the line? if line.split(" ").length<1 startNewFile=true else if startNewFile oldFile.flush if oldFile tmpf=oldFile=Tempfile.new("eplot") files.push(tmpf) startNewFile=false end tmpf.puts line end end if tmpf tmpf.flush else $stderr.printf "%sFile '%s' is empty!\n",$err,filename exit 1 end file.close # ---- Call it as if we had multiple files removeDummyTitles(files.length) runMulFrMulOpenedFiles(files) files.each { |f| f.close } end # -------------------------------------------------------------------------- # ---- run from a single file. # ---- either a single or multiple diagrams def runFrOneOrMoreFiles(filenames) # ---- Multiple curves in a single diagram from a single file # ---- or repeated across multiple files if @oc["MulFrSin"] filenames.each { |fn| runMulFrSin(fn) } else # ---- Multiple curves in a single diagram from different files if @oc["MulFrMul"] runMulFrMul(filenames) else if @oc["MulFrSeq"] filenames.each { |fn| runMulFrSeq(fn) } # ---- Default: a separate curve for each file else filenames.each { |fn| runSinFrSin(fn) } end end end end # -------------------------------------------------------------------------- # ---- run on input = standard input def runFrStdin tmpf=Tempfile.new("eplot") $stdin.each_line { |x| tmpf.print x } tmpf.flush runFrOneOrMoreFiles([tmpf.path]) tmpf.close end # -------------------------------------------------------------------------- # ---- run the application def run # ---- run from stdin if @oc["Files"].length < 1 runFrStdin # ---- run from a given file list else runFrOneOrMoreFiles(@oc["Files"]) end end end # -------------------------------------------------------------------------- # The main program # -------------------------------------------------------------------------- $c=Controller.new $c.run