From b5275d6386c126df797819faab789625c661f6ea Mon Sep 17 00:00:00 2001 From: Dima Kogan Date: Mon, 14 Jan 2019 18:18:19 -0800 Subject: [PATCH] manually extracted README.pod to a file to work around github bug --- README.pod | 1048 +++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 1047 insertions(+), 1 deletion(-) mode change 120000 => 100644 README.pod diff --git a/README.pod b/README.pod deleted file mode 120000 index abe0c14..0000000 --- a/README.pod +++ /dev/null @@ -1 +0,0 @@ -bin/feedgnuplot \ No newline at end of file diff --git a/README.pod b/README.pod new file mode 100644 index 0000000..5cbe3c9 --- /dev/null +++ b/README.pod @@ -0,0 +1,1047 @@ +.\" Automatically generated by Pod::Man 4.09 (Pod::Simple 3.35) +.\" +.\" Standard preamble: +.\" ======================================================================== +.de Sp \" Vertical space (when we can't use .PP) +.if t .sp .5v +.if n .sp +.. +.de Vb \" Begin verbatim text +.ft CW +.nf +.ne \\$1 +.. +.de Ve \" End verbatim text +.ft R +.fi +.. +.\" Set up some character translations and predefined strings. \*(-- will +.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left +.\" double quote, and \*(R" will give a right double quote. \*(C+ will +.\" give a nicer C++. Capital omega is used to do unbreakable dashes and +.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, +.\" nothing in troff, for use with C<>. +.tr \(*W- +.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' +.ie n \{\ +. ds -- \(*W- +. ds PI pi +. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch +. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch +. ds L" "" +. ds R" "" +. ds C` "" +. ds C' "" +'br\} +.el\{\ +. ds -- \|\(em\| +. ds PI \(*p +. ds L" `` +. ds R" '' +. ds C` +. ds C' +'br\} +.\" +.\" Escape single quotes in literal strings from groff's Unicode transform. +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.\" +.\" If the F register is >0, we'll generate index entries on stderr for +.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index +.\" entries marked with X<> in POD. Of course, you'll have to process the +.\" output yourself in some meaningful fashion. +.\" +.\" Avoid warning from groff about undefined register 'F'. +.de IX +.. +.if !\nF .nr F 0 +.if \nF>0 \{\ +. de IX +. tm Index:\\$1\t\\n%\t"\\$2" +.. +. if !\nF==2 \{\ +. nr % 0 +. nr F 2 +. \} +.\} +.\" +.\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). +.\" Fear. Run. Save yourself. No user-serviceable parts. +. \" fudge factors for nroff and troff +.if n \{\ +. ds #H 0 +. ds #V .8m +. ds #F .3m +. ds #[ \f1 +. ds #] \fP +.\} +.if t \{\ +. ds #H ((1u-(\\\\n(.fu%2u))*.13m) +. ds #V .6m +. ds #F 0 +. ds #[ \& +. ds #] \& +.\} +. \" simple accents for nroff and troff +.if n \{\ +. ds ' \& +. ds ` \& +. ds ^ \& +. ds , \& +. ds ~ ~ +. ds / +.\} +.if t \{\ +. ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" +. ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' +. ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' +. ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' +. ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' +. ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' +.\} +. \" troff and (daisy-wheel) nroff accents +.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' +.ds 8 \h'\*(#H'\(*b\h'-\*(#H' +.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] +.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' +.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' +.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] +.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] +.ds ae a\h'-(\w'a'u*4/10)'e +.ds Ae A\h'-(\w'A'u*4/10)'E +. \" corrections for vroff +.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' +.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' +. \" for low resolution devices (crt and lpr) +.if \n(.H>23 .if \n(.V>19 \ +\{\ +. ds : e +. ds 8 ss +. ds o a +. ds d- d\h'-1'\(ga +. ds D- D\h'-1'\(hy +. ds th \o'bp' +. ds Th \o'LP' +. ds ae ae +. ds Ae AE +.\} +.rm #[ #] #H #V #F C +.\" ======================================================================== +.\" +.IX Title "FEEDGNUPLOT 1" +.TH FEEDGNUPLOT 1 "2018-11-30" "perl v5.26.1" "User Contributed Perl Documentation" +.\" For nroff, turn off justification. Always turn off hyphenation; it makes +.\" way too many mistakes in technical documents. +.if n .ad l +.nh +.SH "NAME" +feedgnuplot \- General purpose pipe\-oriented plotting tool +.SH "SYNOPSIS" +.IX Header "SYNOPSIS" +Simple plotting of piped data: +.PP +.Vb 6 +\& $ seq 5 | awk \*(Aq{print 2*$1, $1*$1}\*(Aq +\& 2 1 +\& 4 4 +\& 6 9 +\& 8 16 +\& 10 25 +\& +\& $ seq 5 | awk \*(Aq{print 2*$1, $1*$1}\*(Aq | +\& feedgnuplot \-\-lines \-\-points \-\-legend 0 "data 0" \-\-title "Test plot" \-\-y2 1 +\& \-\-unset grid \-\-terminal \*(Aqdumb 80,40\*(Aq \-\-exit +\& +\& Test plot +\& +\& 10 +\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-+ 25 +\& | + + + + + + + *##| +\& | data 0 ***A*#* | +\& | ** # | +\& 9 |\-+ ** ## | +\& | ** # | +\& | ** # | +\& | ** ## +\-| 20 +\& 8 |\-+ A # | +\& | ** # | +\& | ** ## | +\& | ** # | +\& | ** B | +\& 7 |\-+ ** ## | +\& | ** ## +\-| 15 +\& | ** # | +\& | ** ## | +\& 6 |\-+ *A ## | +\& | ** ## | +\& | ** # | +\& | ** ## +\-| 10 +\& 5 |\-+ ** ## | +\& | ** #B | +\& | ** ## | +\& | ** ## | +\& 4 |\-+ A ### | +\& | ** ## | +\& | ** ## +\-| 5 +\& | ** ## | +\& | ** ##B# | +\& 3 |\-+ ** #### | +\& | **#### | +\& | #### | +\& |## + + + + + + + | +\& 2 +\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-+ 0 +\& 1 1.5 2 2.5 3 3.5 4 4.5 5 +.Ve +.PP +Simple real-time plotting example: plot how much data is received on the wlan0 +network interface in bytes/second (uses bash, awk and Linux): +.PP +.Vb 3 +\& $ while true; do sleep 1; cat /proc/net/dev; done | +\& gawk \*(Aq/wlan0/ {if(b) {print $2\-b; fflush()} b=$2}\*(Aq | +\& feedgnuplot \-\-lines \-\-stream \-\-xlen 10 \-\-ylabel \*(AqBytes/sec\*(Aq \-\-xlabel seconds +.Ve +.SH "DESCRIPTION" +.IX Header "DESCRIPTION" +This is a flexible, command-line-oriented frontend to Gnuplot. It creates +plots from data coming in on \s-1STDIN\s0 or given in a filename passed on the +commandline. Various data representations are supported, as is hardcopy +output and streaming display of live data. A simple example: +.PP +.Vb 1 +\& $ seq 5 | awk \*(Aq{print 2*$1, $1*$1}\*(Aq | feedgnuplot +.Ve +.PP +You should see a plot with two curves. The \f(CW\*(C`awk\*(C'\fR command generates some data to +plot and the \f(CW\*(C`feedgnuplot\*(C'\fR reads it in from \s-1STDIN\s0 and generates the plot. The +\&\f(CW\*(C`awk\*(C'\fR invocation is just an example; more interesting things would be plotted +in normal usage. No commandline-options are required for the most basic +plotting. Input parsing is flexible; every line need not have the same number of +points. New curves will be created as needed. +.PP +The most commonly used functionality of gnuplot is supported directly by the +script. Anything not directly supported can still be done with options such as +\&\f(CW\*(C`\-\-set\*(C'\fR, \f(CW\*(C`\-\-extracmds\*(C'\fR \f(CW\*(C`\-\-style\*(C'\fR, etc. Arbitrary gnuplot commands can be +passed in with \f(CW\*(C`\-\-extracmds\*(C'\fR. For example, to turn off the grid, you can pass +in \f(CW\*(C`\-\-extracmds \*(Aqunset grid\*(Aq\*(C'\fR. Commands \f(CW\*(C`\-\-set\*(C'\fR and \f(CW\*(C`\-\-unset\*(C'\fR exists to +provide nicer syntax, so this is equivalent to passing \f(CW\*(C`\-\-unset grid\*(C'\fR. As many +of these options as needed can be passed in. To add arbitrary curve styles, use +\&\f(CW\*(C`\-\-style curveID extrastyle\*(C'\fR. Pass these more than once to affect more than one +curve. +.PP +To apply an extra style to \fIall\fR the curves that lack an explicit \f(CW\*(C`\-\-style\*(C'\fR, +pass in \f(CW\*(C`\-\-styleall extrastyle\*(C'\fR. In the most common case, the extra style is +\&\f(CW\*(C`with something\*(C'\fR. To support this more simply, you can pass in \f(CW\*(C`\-\-with +something\*(C'\fR instead of \f(CW\*(C`\-\-styleall \*(Aqwith something\*(Aq\*(C'\fR. \f(CW\*(C`\-\-styleall\*(C'\fR and +\&\f(CW\*(C`\-\-with\*(C'\fR are mutually exclusive. Furthermore any curve-specific \f(CW\*(C`\-\-style\*(C'\fR +overrides the global \f(CW\*(C`\-\-styleall\*(C'\fR or \f(CW\*(C`\-\-with\*(C'\fR setting. +.SS "Data formats" +.IX Subsection "Data formats" +By default, each value present in the incoming data represents a distinct data +point, as demonstrated in the original example above (we had 10 numbers in the +input and 10 points in the plot). If requested, the script supports more +sophisticated interpretation of input data +.PP +\fIDomain selection\fR +.IX Subsection "Domain selection" +.PP +If \f(CW\*(C`\-\-domain\*(C'\fR is passed in, the first value on each line of input is +interpreted as the \fIX\fR\-value for the rest of the data on that line. Without +\&\f(CW\*(C`\-\-domain\*(C'\fR the \fIX\fR\-value is the line number, and the first value on a line is +a plain data point like the others. Default is \f(CW\*(C`\-\-nodomain\*(C'\fR. Thus the original +example above produces 2 curves, with \fB1,2,3,4,5\fR as the \fIX\fR\-values. If we run +the same command with \f(CW\*(C`\-\-domain\*(C'\fR: +.PP +.Vb 1 +\& $ seq 5 | awk \*(Aq{print 2*$1, $1*$1}\*(Aq | feedgnuplot \-\-domain +.Ve +.PP +we get only 1 curve, with \fB2,4,6,8,10\fR as the \fIX\fR\-values. As many points as +desired can appear on a single line, but all points on a line are associated +with the \fIX\fR\-value at the start of that line. +.PP +\fICurve indexing\fR +.IX Subsection "Curve indexing" +.PP +We index the curves in one of 3 ways: sequentially, explicitly with a +\&\f(CW\*(C`\-\-dataid\*(C'\fR or by \f(CW\*(C`\-\-vnlog\*(C'\fR headers. +.PP +By default, each column represents a separate curve. The first column (after any +domain) is curve \f(CW0\fR. The next one is curve \f(CW1\fR and so on. This is fine unless +sparse data is to be plotted. With the \f(CW\*(C`\-\-dataid\*(C'\fR option, each point is +represented by 2 values: a string identifying the curve, and the value itself. +If we add \f(CW\*(C`\-\-dataid\*(C'\fR to the original example: +.PP +.Vb 1 +\& $ seq 5 | awk \*(Aq{print 2*$1, $1*$1}\*(Aq | feedgnuplot \-\-dataid \-\-autolegend +.Ve +.PP +we get 5 different curves with one point in each. The first column, as produced +by \f(CW\*(C`awk\*(C'\fR, is \fB2,4,6,8,10\fR. These are interpreted as the IDs of the curves to +be plotted. +.PP +If we're plotting \f(CW\*(C`vnlog\*(C'\fR data () then we +can get the curve IDs from the vnlog header. Vnlog is a trivial data format +where lines starting with \f(CW\*(C`#\*(C'\fR are comments and the first comment contains +column labels. If we have such data, \f(CW\*(C`feedgnuplot \-\-vnlog\*(C'\fR can interpret these +column labels if the \f(CW\*(C`vnlog\*(C'\fR perl modules are available. +.PP +The \f(CW\*(C`\-\-autolegend\*(C'\fR option adds a legend using the given IDs to +label the curves. The IDs need not be numbers; generic strings are accepted. As +many points as desired can appear on a single line. \f(CW\*(C`\-\-domain\*(C'\fR can be used in +conjunction with \f(CW\*(C`\-\-dataid\*(C'\fR or \f(CW\*(C`\-\-vnlog\*(C'\fR. +.PP +\fIMulti-value style support\fR +.IX Subsection "Multi-value style support" +.PP +Depending on how gnuplot is plotting the data, more than one value may be needed +to represent the range of a single point. Basic 2D plots have 2 numbers +representing each point: 1 domain and 1 range. But if plotting with +\&\f(CW\*(C`\-\-circles\*(C'\fR, for instance, then there's an extra range value: the radius. Many +other gnuplot styles require more data: errorbars, variable colors (\f(CW\*(C`with +points palette\*(C'\fR), variable sizes (\f(CW\*(C`with points ps variable\*(C'\fR), labels and so on. +The feedgnuplot tool itself does not know about all these intricacies, but they +can still be used, by specifying the specific style with \f(CW\*(C`\-\-style\*(C'\fR, and +specifying how many values are needed for each point with any of +\&\f(CW\*(C`\-\-rangesizeall\*(C'\fR, \f(CW\*(C`\-\-tuplesizeall\*(C'\fR, \f(CW\*(C`\-\-rangesize\*(C'\fR, \f(CW\*(C`\-\-tuplesize\*(C'\fR. These +options are required \fIonly\fR for styles not explicitly supported by feedgnuplot; +supported styles do the right thing automatically. +.PP +Specific example: if making a 2d plot of y error bars, the exact format can be +queried by running \f(CW\*(C`gnuplot\*(C'\fR and invoking \f(CW\*(C`help yerrorbars\*(C'\fR. This tells us +that there's a 3\-column form: \f(CW\*(C`x y ydelta\*(C'\fR and a 4\-column form: \f(CW\*(C`x y ylow +yhigh\*(C'\fR. With 2d plots feedgnuplot will always output the 1\-value domain \f(CW\*(C`x\*(C'\fR, so +the rangesize is 2 and 3 respectively. Thus the following are equivalent: +.PP +.Vb 3 +\& $ echo \*(Aq1 2 0.3 +\& 2 3 0.4 +\& 3 4 0.5\*(Aq | feedgnuplot \-\-domain \-\-rangesizeall 2 \-\-with \*(Aqyerrorbars\*(Aq +\& +\& $ echo \*(Aq1 2 0.3 +\& 2 3 0.4 +\& 3 4 0.5\*(Aq | feedgnuplot \-\-domain \-\-tuplesizeall 3 \-\-with \*(Aqyerrorbars\*(Aq +\& +\& $ echo \*(Aq1 2 1.7 2.3 +\& 2 3 2.6 3.4 +\& 3 4 3.5 4.5\*(Aq | feedgnuplot \-\-domain \-\-rangesizeall 3 \-\-with \*(Aqyerrorbars\*(Aq +.Ve +.PP +\fI3D data\fR +.IX Subsection "3D data" +.PP +To plot 3D data, pass in \f(CW\*(C`\-\-3d\*(C'\fR. \f(CW\*(C`\-\-domain\*(C'\fR \s-1MUST\s0 be given when plotting 3D +data to avoid domain ambiguity. If 3D data is being plotted, there are by +definition 2 domain values instead of one (\fIZ\fR as a function of \fIX\fR and \fIY\fR +instead of \fIY\fR as a function of \fIX\fR). Thus the first 2 values on each line are +interpreted as the domain instead of just 1. The rest of the processing happens +the same way as before. +.PP +\fITime/date data\fR +.IX Subsection "Time/date data" +.PP +If the input data domain is a time/date, this can be interpreted with +\&\f(CW\*(C`\-\-timefmt\*(C'\fR. This option takes a single argument: the format to use to parse +the data. The format is documented in 'set timefmt' in gnuplot, although the +common flags that \f(CW\*(C`strftime\*(C'\fR understands are generally supported. The backslash +sequences in the format are \fInot\fR supported, so if you want a tab, put in a tab +instead of \et. Whitespace in the format \fIis\fR supported. When this flag is +given, some other options act a little bit differently: +.IP "\(bu" 4 +\&\f(CW\*(C`\-\-xlen\*(C'\fR is an \fIinteger\fR in seconds +.IP "\(bu" 4 +\&\f(CW\*(C`\-\-xmin\*(C'\fR and \f(CW\*(C`\-\-xmax\*(C'\fR \fImust\fR use the format passed in to \f(CW\*(C`\-\-timefmt\*(C'\fR +.PP +Using this option changes both the way the input is parsed \fIand\fR the way the +x\-axis tics are labelled. Gnuplot tries to be intelligent in this labelling, but +it doesn't always do what the user wants. The labelling can be controlled with +the gnuplot \f(CW\*(C`set format\*(C'\fR command, which takes the same type of format string as +\&\f(CW\*(C`\-\-timefmt\*(C'\fR. Example: +.PP +.Vb 5 +\& $ sar 1 \-1 | +\& awk \*(Aq$1 ~ /..:..:../ && $8 ~/^[0\-9\e.]*$/ {print $1,$8; fflush()}\*(Aq | +\& feedgnuplot \-\-stream \-\-domain +\& \-\-lines \-\-timefmt \*(Aq%H:%M:%S\*(Aq +\& \-\-set \*(Aqformat x "%H:%M:%S"\*(Aq +.Ve +.PP +This plots the 'idle' \s-1CPU\s0 consumption against time. +.PP +Note that while gnuplot supports the time/date on any axis, \fIfeedgnuplot\fR +currently supports it \fIonly\fR as the x\-axis domain. This may change in the +future. +.SS "Real-time streaming data" +.IX Subsection "Real-time streaming data" +To plot real-time data, pass in the \f(CW\*(C`\-\-stream [refreshperiod]\*(C'\fR option. Data +will then be plotted as it is received. The plot will be updated every +\&\f(CW\*(C`refreshperiod\*(C'\fR seconds. If the period isn't specified, a 1Hz refresh rate is +used. To refresh at specific intervals indicated by the data, set the +refreshperiod to 0 or to 'trigger'. The plot will then \fIonly\fR be refreshed when +a data line 'replot' is received. This 'replot' command works in both triggered +and timed modes, but in triggered mode, it's the only way to replot. Look in +\&\*(L"Special data commands\*(R" for more information. +.PP +To plot only the most recent data (instead of \fIall\fR the data), \f(CW\*(C`\-\-xlen +windowsize\*(C'\fR can be given. This will create an constantly-updating, scrolling +view of the recent past. \f(CW\*(C`windowsize\*(C'\fR should be replaced by the desired length +of the domain window to plot, in domain units (passed-in values if \f(CW\*(C`\-\-domain\*(C'\fR +or line numbers otherwise). If the domain is a time/date via \f(CW\*(C`\-\-timefmt\*(C'\fR, then +\&\f(CW\*(C`windowsize\*(C'\fR is and \fIinteger\fR in seconds. If we're plotting a histogram, then +\&\f(CW\*(C`\-\-xlen\*(C'\fR causes a histogram over a moving window to be computed. The subtlely +here is that with a histogram you don't actually \fIsee\fR the domain since only +the range is analyzed. But the domain is still there, and can be utilized with +\&\f(CW\*(C`\-\-xlen\*(C'\fR. With \f(CW\*(C`\-\-xlen\*(C'\fR we can plot \fIonly\fR histograms or \fIonly\fR +\&\fInon\fR\-histograms. +.PP +\fISpecial data commands\fR +.IX Subsection "Special data commands" +.PP +If we are reading streaming data, the input stream can contain special commands +in addition to the raw data. Feedgnuplot looks for these at the start of every +input line. If a command is detected, the rest of the line is discarded. These +commands are +.ie n .IP """replot""" 4 +.el .IP "\f(CWreplot\fR" 4 +.IX Item "replot" +This command refreshes the plot right now, instead of waiting for the next +refresh time indicated by the timer. This command works in addition to the timed +refresh, as indicated by \f(CW\*(C`\-\-stream [refreshperiod]\*(C'\fR. +.ie n .IP """clear""" 4 +.el .IP "\f(CWclear\fR" 4 +.IX Item "clear" +This command clears out the current data in the plot. The plotting process +continues, however, to any data following the \f(CW\*(C`clear\*(C'\fR. +.ie n .IP """exit""" 4 +.el .IP "\f(CWexit\fR" 4 +.IX Item "exit" +This command causes feedgnuplot to exit. +.SS "Hardcopy output" +.IX Subsection "Hardcopy output" +The script is able to produce hardcopy output with \f(CW\*(C`\-\-hardcopy outputfile\*(C'\fR. The +output type can be inferred from the filename, if \fB.ps\fR, \fB.eps\fR, \fB.pdf\fR, +\&\fB.svg\fR, \fB.png\fR or \fB.gp\fR is requested. If any other file type is requested, +\&\f(CW\*(C`\-\-terminal\*(C'\fR \fImust\fR be passed in to tell gnuplot how to make the plot. If +\&\f(CW\*(C`\-\-terminal\*(C'\fR is passed in, then the \f(CW\*(C`\-\-hardcopy\*(C'\fR argument only provides the +output filename. +.PP +The \fB.gp\fR output is special. Instead of asking gnuplot to plot to a particular +terminal, writing to a \fB.gp\fR simply dumps a self-executable gnuplot script into +the given file. This is similar to what \f(CW\*(C`\-\-dump\*(C'\fR does, but writes to a file, +and makes sure that the file can be self-executing. +.SS "Self-plotting data files" +.IX Subsection "Self-plotting data files" +This script can be used to enable self-plotting data files. There are several +ways of doing this: with a shebang (#!) or with inline perl data. +.PP +\fISelf-plotting data with a #!\fR +.IX Subsection "Self-plotting data with a #!" +.PP +A self-plotting, executable data file \f(CW\*(C`data\*(C'\fR is formatted as +.PP +.Vb 10 +\& $ cat data +\& #!/usr/bin/feedgnuplot \-\-lines \-\-points +\& 2 1 +\& 4 4 +\& 6 9 +\& 8 16 +\& 10 25 +\& 12 36 +\& 14 49 +\& 16 64 +\& 18 81 +\& 20 100 +\& 22 121 +\& 24 144 +\& 26 169 +\& 28 196 +\& 30 225 +.Ve +.PP +This is the shebang (#!) line followed by the data, formatted as before. The +data file can be plotted simply with +.PP +.Vb 1 +\& $ ./data +.Ve +.PP +The caveats here are that on Linux the whole #! line is limited to 127 +characters and that the full path to feedgnuplot must be given. The 127 +character limit is a serious limitation, but this can likely be resolved with a +kernel patch. I have only tried on Linux 2.6. +.PP +\fISelf-plotting data with gnuplot\fR +.IX Subsection "Self-plotting data with gnuplot" +.PP +Running \f(CW\*(C`feedgnuplot \-\-hardcopy plotdata.gp ....\*(C'\fR will create a self-executable +gnuplot script in \f(CW\*(C`plotdata.gp\*(C'\fR +.PP +\fISelf-plotting data with perl inline data\fR +.IX Subsection "Self-plotting data with perl inline data" +.PP +Perl supports storing data and code in the same file. This can also be used to +create self-plotting files: +.PP +.Vb 4 +\& $ cat plotdata.pl +\& #!/usr/bin/perl +\& use strict; +\& use warnings; +\& +\& open PLOT, "| feedgnuplot \-\-lines \-\-points" or die "Couldn\*(Aqt open plotting pipe"; +\& while( ) +\& { +\& my @xy = split; +\& print PLOT "@xy\en"; +\& } +\& _\|_DATA_\|_ +\& 2 1 +\& 4 4 +\& 6 9 +\& 8 16 +\& 10 25 +\& 12 36 +\& 14 49 +\& 16 64 +\& 18 81 +\& 20 100 +\& 22 121 +\& 24 144 +\& 26 169 +\& 28 196 +\& 30 225 +.Ve +.PP +This is especially useful if the logged data is not in a format directly +supported by feedgnuplot. Raw data can be stored after the _\|_DATA_\|_ directive, +with a small perl script to manipulate the data into a useable format and send +it to the plotter. +.SH "ARGUMENTS" +.IX Header "ARGUMENTS" +.IP "\(bu" 4 +\&\-\-\f(CW\*(C`[no]domain\*(C'\fR +.Sp +If enabled, the first element of each line is the domain variable. If not, the +point index is used +.IP "\(bu" 4 +\&\-\-\f(CW\*(C`[no]dataid\*(C'\fR +.Sp +If enabled, each data point is preceded by the \s-1ID\s0 of the data set that point +corresponds to. This \s-1ID\s0 is interpreted as a string, \s-1NOT\s0 as just a number. If not +enabled, the order of the point is used. +.Sp +As an example, if line 3 of the input is \*(L"0 9 1 20\*(R" then +.RS 4 +.IP "\(bu" 4 +\&\f(CW\*(C`\-\-nodomain \-\-nodataid\*(C'\fR would parse the 4 numbers as points in 4 different +curves at x=3 +.IP "\(bu" 4 +\&\f(CW\*(C`\-\-domain \-\-nodataid\*(C'\fR would parse the 4 numbers as points in 3 different +curves at x=0. Here, 0 is the x\-variable and 9,1,20 are the data values +.IP "\(bu" 4 +\&\f(CW\*(C`\-\-nodomain \-\-dataid\*(C'\fR would parse the 4 numbers as points in 2 different +curves at x=3. Here 0 and 1 are the data IDs and 9 and 20 are the +data values +.IP "\(bu" 4 +\&\f(CW\*(C`\-\-domain \-\-dataid\*(C'\fR would parse the 4 numbers as a single point at +x=0. Here 9 is the data \s-1ID\s0 and 1 is the data value. 20 is an extra +value, so it is ignored. If another value followed 20, we'd get another +point in curve \s-1ID 20\s0 +.RE +.RS 4 +.RE +.IP "\(bu" 4 +\&\f(CW\*(C`\-\-vnlog\*(C'\fR +.Sp +Vnlog is a trivial data format where lines starting with \f(CW\*(C`#\*(C'\fR are comments and +the first comment contains column labels. Some tools for working with such data +are available from the \f(CW\*(C`vnlog\*(C'\fR project: . +With the \f(CW\*(C`vnlog\*(C'\fR perl modules installed, we can read the vnlog column headers +with \f(CW\*(C`feedgnuplot \-\-vnlog\*(C'\fR. This replaces \f(CW\*(C`\-\-dataid\*(C'\fR, and we can do all the +normal things with these headers. For instance \f(CW\*(C`feedgnuplot \-\-vnlog +\&\-\-autolegend\*(C'\fR will generate plot legends for each column in the vnlog, using the +vnlog column label in the legend. +.IP "\(bu" 4 +\&\f(CW\*(C`\-\-[no]3d\*(C'\fR +.Sp +Do [not] plot in 3D. This only makes sense with \f(CW\*(C`\-\-domain\*(C'\fR. Each domain here is +an (x,y) tuple +.IP "\(bu" 4 +\&\-\-\f(CW\*(C`timefmt [format]\*(C'\fR +.Sp +Interpret the X data as a time/date, parsed with the given format +.IP "\(bu" 4 +\&\f(CW\*(C`\-\-colormap\*(C'\fR +.Sp +Show a colormapped xy plot. Requires extra data for the color. zmin/zmax can be +used to set the extents of the colors. Automatically sets the +\&\f(CW\*(C`\-\-rangesize\*(C'\fR/\f(CW\*(C`\-\-tuplesize\*(C'\fR. +.IP "\(bu" 4 +\&\f(CW\*(C`\-\-stream [period]\*(C'\fR +.Sp +Plot the data as it comes in, in realtime. If period is given, replot every +period seconds. If no period is given, replot at 1Hz. If the period is given as +0 or 'trigger', replot \fIonly\fR when the incoming data dictates this. See the +\&\*(L"Real-time streaming data\*(R" section of the man page. +.IP "\(bu" 4 +\&\f(CW\*(C`\-\-[no]lines\*(C'\fR +.Sp +Do [not] draw lines to connect consecutive points +.IP "\(bu" 4 +\&\f(CW\*(C`\-\-[no]points\*(C'\fR +.Sp +Do [not] draw points +.IP "\(bu" 4 +\&\f(CW\*(C`\-\-circles\*(C'\fR +.Sp +Plot with circles. This requires a radius be specified for each point. +Automatically sets the \f(CW\*(C`\-\-rangesize\*(C'\fR/\f(CW\*(C`\-\-tuplesize\*(C'\fR. \f(CW\*(C`Not\*(C'\fR supported for 3d +plots. +.IP "\(bu" 4 +\&\f(CW\*(C`\-\-title xxx\*(C'\fR +.Sp +Set the title of the plot +.IP "\(bu" 4 +\&\f(CW\*(C`\-\-legend curveID legend\*(C'\fR +.Sp +Set the label for a curve plot. Use this option multiple times for multiple +curves. With \f(CW\*(C`\-\-dataid\*(C'\fR, curveID is the \s-1ID.\s0 Otherwise, it's the index of the +curve, starting at 0 +.IP "\(bu" 4 +\&\f(CW\*(C`\-\-autolegend\*(C'\fR +.Sp +Use the curve IDs for the legend. Titles given with \f(CW\*(C`\-\-legend\*(C'\fR override these +.IP "\(bu" 4 +\&\f(CW\*(C`\-\-xlen xxx\*(C'\fR +.Sp +When using \f(CW\*(C`\-\-stream\*(C'\fR, sets the size of the x\-window to plot. Omit this or set +it to 0 to plot \s-1ALL\s0 the data. Does not make sense with 3d plots. Implies +\&\f(CW\*(C`\-\-monotonic\*(C'\fR. If we're plotting a histogram, then \f(CW\*(C`\-\-xlen\*(C'\fR causes a histogram +over a moving window to be computed. The subtlely here is that with a histogram +you don't actually \fIsee\fR the domain since only the range is analyzed. But the +domain is still there, and can be utilized with \f(CW\*(C`\-\-xlen\*(C'\fR. With \f(CW\*(C`\-\-xlen\*(C'\fR we can +plot \fIonly\fR histograms or \fIonly\fR \fInon\fR\-histograms. +.IP "\(bu" 4 +\&\f(CW\*(C`\-\-xmin/xmax/ymin/ymax/y2min/y2max/zmin/zmax xxx\*(C'\fR +.Sp +Set the range for the given axis. These x\-axis bounds are ignored in a streaming +plot. The y2\-axis bound do not apply in 3d plots. The z\-axis bounds apply +\&\fIonly\fR to 3d plots or colormaps. Note that there is no \f(CW\*(C`\-\-xrange\*(C'\fR to set both +sides at once or \f(CW\*(C`\-\-xinv\*(C'\fR to flip the axis around: anything more than the +basics supported in this option is clearly obtainable by talking to gnuplot, for +instance \f(CW\*(C`\-\-set \*(Aqxrange [20:10]\*(Aq\*(C'\fR to set the given inverted bounds. +.IP "\(bu" 4 +\&\f(CW\*(C`\-\-xlabel/ylabel/y2label/zlabel xxx\*(C'\fR +.Sp +Label the given axis. The y2\-axis label does not apply to 3d plots while the +z\-axis label applies \fIonly\fR to 3d plots. +.IP "\(bu" 4 +\&\f(CW\*(C`\-\-y2 xxx\*(C'\fR +.Sp +Plot the data specified by this curve \s-1ID\s0 on the y2 axis. Without \f(CW\*(C`\-\-dataid\*(C'\fR, +the \s-1ID\s0 is just an ordered 0\-based index. Does not apply to 3d plots. Can be +passed multiple times, or passed a comma-separated list. By default the y2\-axis +curves look the same as the y\-axis ones. I.e. the viewer of the resulting plot +has to be told which is which via an axes label, legend, etc. Prior to version +1.25 of feedgnuplot the curves plotted on the y2 axis were drawn with a thicker +line. This is no longer the case, but that behavior can be brought back by +passing something like +.Sp +.Vb 1 +\& \-\-y2 curveid \-\-style curveid \*(Aqlinewidth 3\*(Aq +.Ve +.IP "\(bu" 4 +\&\f(CW\*(C`\-\-histogram curveID\*(C'\fR +.Sp +Set up a this specific curve to plot a histogram. The bin width is given with +the \f(CW\*(C`\-\-binwidth\*(C'\fR option (assumed 1.0 if omitted). If a drawing style is not +specified for this curve (\f(CW\*(C`\-\-curvestyle\*(C'\fR) or all curves (\f(CW\*(C`\-\-with\*(C'\fR, +\&\f(CW\*(C`\-\-curvestyleall\*(C'\fR) then the default histogram style is set: filled boxes with +borders. This is what the user generally wants. This works with \f(CW\*(C`\-\-domain\*(C'\fR +and/or \f(CW\*(C`\-\-stream\*(C'\fR, but in those cases the x\-value is used \fIonly\fR to cull old +data because of \f(CW\*(C`\-\-xlen\*(C'\fR or \f(CW\*(C`\-\-monotonic\*(C'\fR. I.e. the domain values are \fInot\fR +drawn in any way. Can be passed multiple times, or passed a comma\- separated +list +.IP "\(bu" 4 +\&\f(CW\*(C`\-\-binwidth width\*(C'\fR +.Sp +The width of bins when making histograms. This setting applies to \s-1ALL\s0 histograms +in the plot. Defaults to 1.0 if not given. +.IP "\(bu" 4 +\&\f(CW\*(C`\-\-histstyle style\*(C'\fR +.Sp +Normally, histograms are generated with the 'smooth frequency' gnuplot style. +\&\f(CW\*(C`\-\-histstyle\*(C'\fR can be used to select different \f(CW\*(C`smooth\*(C'\fR settings (see the +gnuplot \f(CW\*(C`help smooth\*(C'\fR page for more info). Allowed values are 'frequency' (the +default), 'fnormal' (available in very recent gnuplots), 'unique', 'cumulative' +and 'cnormal'. 'fnormal' is a normalized histogram. 'unique' indicates whether a +bin has at least one item in it: instead of counting the items, it'll always +report 0 or 1. 'cumulative' is the integral of the 'frequency' histogram. +\&'cnormal' is like 'cumulative', but rescaled to end up at 1.0. +.IP "\(bu" 4 +\&\f(CW\*(C`\-\-style curveID style\*(C'\fR +.Sp +Additional styles per curve. With \f(CW\*(C`\-\-dataid\*(C'\fR, curveID is the \s-1ID.\s0 Otherwise, +it's the index of the curve, starting at 0. curveID can be a comma-separated +list of IDs to which the given style should apply. Use this option multiple +times for multiple curves. \f(CW\*(C`\-\-styleall\*(C'\fR does \fInot\fR apply to curves that have a +\&\f(CW\*(C`\-\-style\*(C'\fR. +.IP "\(bu" 4 +\&\f(CW\*(C`\-\-curvestyle curveID\*(C'\fR +.Sp +Synonym for \f(CW\*(C`\-\-style\*(C'\fR +.IP "\(bu" 4 +\&\f(CW\*(C`\-\-styleall xxx\*(C'\fR +.Sp +Additional styles for all curves that have no \f(CW\*(C`\-\-style\*(C'\fR. This is overridden by +any applicable \f(CW\*(C`\-\-style\*(C'\fR. Exclusive with \f(CW\*(C`\-\-with\*(C'\fR. +.IP "\(bu" 4 +\&\f(CW\*(C`\-\-curvestyleall xxx\*(C'\fR +.Sp +Synonym for \f(CW\*(C`\-\-styleall\*(C'\fR +.IP "\(bu" 4 +\&\f(CW\*(C`\-\-with xxx\*(C'\fR +.Sp +Same as \f(CW\*(C`\-\-styleall\*(C'\fR, but prefixed with \*(L"with\*(R". Thus +.Sp +.Vb 1 +\& \-\-with boxes +.Ve +.Sp +is equivalent to +.Sp +.Vb 1 +\& \-\-styleall \*(Aqwith boxes\*(Aq +.Ve +.Sp +Exclusive with \f(CW\*(C`\-\-styleall\*(C'\fR. +.IP "\(bu" 4 +\&\f(CW\*(C`\-\-extracmds xxx\*(C'\fR +.Sp +Additional commands to pass on to gnuplot verbatim. These could contain extra +global styles for instance. Can be passed multiple times. +.IP "\(bu" 4 +\&\f(CW\*(C`\-\-set xxx\*(C'\fR +.Sp +Additional 'set' commands to pass on to gnuplot verbatim. \f(CW\*(C`\-\-set \*(Aqa b c\*(Aq\*(C'\fR will +result in gnuplot seeing a \f(CW\*(C`set a b c\*(C'\fR command. Can be passed multiple times. +.IP "\(bu" 4 +\&\f(CW\*(C`\-\-unset xxx\*(C'\fR +.Sp +Additional 'unset' commands to pass on to gnuplot verbatim. \f(CW\*(C`\-\-unset \*(Aqa b c\*(Aq\*(C'\fR +will result in gnuplot seeing a \f(CW\*(C`unset a b c\*(C'\fR command. Can be passed multiple +times. +.IP "\(bu" 4 +\&\f(CW\*(C`\-\-image filename\*(C'\fR +.Sp +Overlays the data on top of a raster image given in \f(CW\*(C`filename\*(C'\fR. This is passed +through to gnuplot via \f(CW\*(C`\-\-equation\*(C'\fR, and is not interpreted by \f(CW\*(C`feedgnuplot\*(C'\fR +other than checking for existence. Usually images have their origin at the +top-left corner, while plots have it in the bottom-left corner instead. Thus if +the y\-axis extents are not specified (\f(CW\*(C`\-\-ymin\*(C'\fR, \f(CW\*(C`\-\-ymax\*(C'\fR, \f(CW\*(C`\-\-set \*(Aqyrange +\&...\*(Aq\*(C'\fR) this option will also flip around the y axis to make the image appear +properly. Since this option is just a passthrough to gnuplot, finer control can +be achieved by passing in \f(CW\*(C`\-\-equation\*(C'\fR and \f(CW\*(C`\-\-set yrange ...\*(C'\fR directly. +.Sp +\&\f(CW\*(C`\-\-equation xxx\*(C'\fR +.Sp +Gnuplot can plot both data and symbolic equations. \f(CW\*(C`feedgnuplot\*(C'\fR generally +plots data, but with this option can plot symbolic equations \fIalso\fR. This is +generally intended to augment data plots, since for equation-only plots you +don't need \f(CW\*(C`feedgnuplot\*(C'\fR. \f(CW\*(C`\-\-equation\*(C'\fR can be passed multiple times for +multiple equations. The given strings are passed to gnuplot directly without +anything added or removed, so styling and such should be applied in the string. +A basic example: +.Sp +.Vb 3 +\& seq 100 | awk \*(Aq{print $1/10, $1/100}\*(Aq | +\& feedgnuplot \-\-with \*(Aqlines lw 3\*(Aq \-\-domain \-\-ymax 1 +\& \-\-equation \*(Aqsin(x)/x\*(Aq \-\-equation \*(Aqcos(x)/x with lines lw 4\*(Aq +.Ve +.Sp +Here I plot the incoming data (points along a line) with the given style (a line +with thickness 3), \fIand\fR I plot two damped sinusoids on the same plot. The +sinusoids are not affected by \f(CW\*(C`feedgnuplot\*(C'\fR styling, so their styles are set +separately, as in this example. More complicated example: +.Sp +.Vb 3 +\& seq 360 | perl \-nE \*(Aq$th=$_/360 * 3.14*2; $c=cos($th); $s=sin($th); say "$c $s"\*(Aq | +\& feedgnuplot \-\-domain \-\-square +\& \-\-set parametric \-\-set "trange [0:2*3.14]" \-\-equation "sin(t),cos(t)" +.Ve +.Sp +Here the data I generate is points along the unit circle. I plot these as +points, and I \fIalso\fR plot a true circle as a parametric equation. +.IP "\(bu" 4 +\&\f(CW\*(C`\-\-square\*(C'\fR +.Sp +Plot data with aspect ratio 1. For 3D plots, this controls the aspect ratio for +all 3 axes +.IP "\(bu" 4 +\&\f(CW\*(C`\-\-square_xy\*(C'\fR +.Sp +For 3D plots, set square aspect ratio for \s-1ONLY\s0 the x,y axes +.IP "\(bu" 4 +\&\f(CW\*(C`\-\-hardcopy xxx\*(C'\fR +.Sp +If not streaming, output to a file specified here. Format inferred from +filename, unless specified by \f(CW\*(C`\-\-terminal\*(C'\fR. If \f(CW\*(C`\-\-terminal\*(C'\fR is given, +\&\f(CW\*(C`\-\-hardcopy\*(C'\fR sets \fIonly\fR the output filename. +.IP "\(bu" 4 +\&\f(CW\*(C`\-\-terminal xxx\*(C'\fR +.Sp +String passed to 'set terminal'. No attempts are made to validate this. +\&\f(CW\*(C`\-\-hardcopy\*(C'\fR sets this to some sensible defaults if \f(CW\*(C`\-\-hardcopy\*(C'\fR is set to a +filename ending in \f(CW\*(C`.png\*(C'\fR, \f(CW\*(C`.pdf\*(C'\fR, \f(CW\*(C`.ps\*(C'\fR, \f(CW\*(C`.eps\*(C'\fR or \f(CW\*(C`.svg\*(C'\fR. If any other +file type is desired, use both \f(CW\*(C`\-\-hardcopy\*(C'\fR and \f(CW\*(C`\-\-terminal\*(C'\fR +.IP "\(bu" 4 +\&\f(CW\*(C`\-\-maxcurves N\*(C'\fR +.Sp +The maximum allowed number of curves. This is 100 by default, but can be reset +with this option. This exists purely to prevent perl from allocating all of the +system's memory when reading bogus data +.IP "\(bu" 4 +\&\f(CW\*(C`\-\-monotonic\*(C'\fR +.Sp +If \f(CW\*(C`\-\-domain\*(C'\fR is given, checks to make sure that the x\-coordinate in the input +data is monotonically increasing. If a given x\-variable is in the past, all data +currently cached for this curve is purged. Without \f(CW\*(C`\-\-monotonic\*(C'\fR, all data is +kept. Does not make sense with 3d plots. No \f(CW\*(C`\-\-monotonic\*(C'\fR by default. The data +is replotted before being purged. This is useful in streaming plots where the +incoming data represents multiple iterations of the same process (repeated +simulations of the same period in time, for instance). +.IP "\(bu" 4 +\&\f(CW\*(C`\-\-rangesize curveID N\*(C'\fR +.Sp +The options \f(CW\*(C`\-\-rangesizeall\*(C'\fR and \f(CW\*(C`\-\-rangesize\*(C'\fR set the number of values are +needed to represent each point being plotted (see \*(L"Multi-value style +support\*(R" above). These options are \fIonly\fR needed if unknown styles are used, +with \f(CW\*(C`\-\-styleall\*(C'\fR or \f(CW\*(C`\-\-with\*(C'\fR for instance. +.Sp +\&\f(CW\*(C`\-\-rangesize\*(C'\fR is used to set how many values are needed to represent the range +of a point for a particular curve. This overrides any defaults that may exist +for this curve only. +.Sp +With \f(CW\*(C`\-\-dataid\*(C'\fR, curveID is the \s-1ID.\s0 Otherwise, it's the index of the curve, +starting at 0. curveID can be a comma-separated list of IDs to which the given +rangesize should apply. +.IP "\(bu" 4 +\&\f(CW\*(C`\-\-tuplesize curveID N\*(C'\fR +.Sp +Very similar to \f(CW\*(C`\-\-rangesize\*(C'\fR, but instead of specifying the \fIrange\fR only, +this specifies the whole tuple. For instance if we're plotting circles, the +tuplesize is 3: \f(CW\*(C`x,y,radius\*(C'\fR. In a 2D plot there's a 1\-dimensional domain: +\&\f(CW\*(C`x\*(C'\fR, so the rangesize is 2: \f(CW\*(C`y,radius\*(C'\fR. This dimensionality can be given +either way. +.IP "\(bu" 4 +\&\f(CW\*(C`\-\-rangesizeall N\*(C'\fR +.Sp +Like \f(CW\*(C`\-\-rangesize\*(C'\fR, but applies to \fIall\fR the curves. +.IP "\(bu" 4 +\&\f(CW\*(C`\-\-tuplesizeall N\*(C'\fR +.Sp +Like \f(CW\*(C`\-\-tuplesize\*(C'\fR, but applies to \fIall\fR the curves. +.IP "\(bu" 4 +\&\f(CW\*(C`\-\-dump\*(C'\fR +.Sp +Instead of printing to gnuplot, print to \s-1STDOUT.\s0 Very useful for debugging. It +is possible to send the output produced this way to gnuplot directly. +.IP "\(bu" 4 +\&\f(CW\*(C`\-\-exit\*(C'\fR +.Sp +This controls what happens when the input data is exhausted, or when some part +of the \f(CW\*(C`feedgnuplot\*(C'\fR pipeline is killed. This option does different things +depending on whether \f(CW\*(C`\-\-stream\*(C'\fR is active, so read this closely. +.Sp +With interactive gnuplot terminals (qt, x11, wxt), the plot windows live in a +separate process from the main \f(CW\*(C`gnuplot\*(C'\fR process. It is thus possible for the +main \f(CW\*(C`gnuplot\*(C'\fR process to exit, while leaving the plot windows up (a caveat is +that such decapitated windows aren't interactive). There are 3 possible states +of the polotting pipeline: +.RS 4 +.ie n .IP "Alive: ""feedgnuplot"", ""gnuplot"" alive, plot window process alive, no shell prompt (shell busy with ""feedgnuplot"")" 4 +.el .IP "Alive: \f(CWfeedgnuplot\fR, \f(CWgnuplot\fR alive, plot window process alive, no shell prompt (shell busy with \f(CWfeedgnuplot\fR)" 4 +.IX Item "Alive: feedgnuplot, gnuplot alive, plot window process alive, no shell prompt (shell busy with feedgnuplot)" +.PD 0 +.ie n .IP "Half-alive: ""feedgnuplot"", ""gnuplot"" dead, plot window process alive (but non-interactive), shell prompt available" 4 +.el .IP "Half-alive: \f(CWfeedgnuplot\fR, \f(CWgnuplot\fR dead, plot window process alive (but non-interactive), shell prompt available" 4 +.IX Item "Half-alive: feedgnuplot, gnuplot dead, plot window process alive (but non-interactive), shell prompt available" +.ie n .IP "Dead: ""feedgnuplot"", ""gnuplot"" dead, plot window process dead, shell prompt available" 4 +.el .IP "Dead: \f(CWfeedgnuplot\fR, \f(CWgnuplot\fR dead, plot window process dead, shell prompt available" 4 +.IX Item "Dead: feedgnuplot, gnuplot dead, plot window process dead, shell prompt available" +.RE +.RS 4 +.PD +.Sp +The possibilities are: +.ie n .IP "No ""\-\-stream"", all data read in" 4 +.el .IP "No \f(CW\-\-stream\fR, all data read in" 4 +.IX Item "No --stream, all data read in" +.RS 4 +.PD 0 +.ie n .IP "no ""\-\-exit"" (default)" 4 +.el .IP "no \f(CW\-\-exit\fR (default)" 4 +.IX Item "no --exit (default)" +.PD +Alive. Need to Ctrl-C to get back into the shell +.ie n .IP """\-\-exit""" 4 +.el .IP "\f(CW\-\-exit\fR" 4 +.IX Item "--exit" +Half-alive. Non-interactive prompt up, and the shell accepts new commands. +Without \f(CW\*(C`\-\-stream\*(C'\fR the goal is to show a plot, so a Dead state would not be +useful. +.RE +.RS 4 +.RE +.ie n .IP """\-\-stream"", all data read in or the ""feedgnuplot"" process terminated" 4 +.el .IP "\f(CW\-\-stream\fR, all data read in or the \f(CWfeedgnuplot\fR process terminated" 4 +.IX Item "--stream, all data read in or the feedgnuplot process terminated" +.RS 4 +.PD 0 +.ie n .IP "no ""\-\-exit"" (default)" 4 +.el .IP "no \f(CW\-\-exit\fR (default)" 4 +.IX Item "no --exit (default)" +.PD +Alive. Need to Ctrl-C to get back into the shell. This means that when making +live plots, the first Ctrl-C kills the data feeding process, but leaves the +final plot up for inspection. A second Ctrl-C kills feedgnuplot as well. +.ie n .IP """\-\-exit""" 4 +.el .IP "\f(CW\-\-exit\fR" 4 +.IX Item "--exit" +Dead. No plot is shown, and the shell accepts new commands. With \f(CW\*(C`\-\-stream\*(C'\fR the +goal is to show a plot as the data comes in, which we have been doing. Now that +we're done, we can clean up everything. +.RE +.RS 4 +.RE +.RE +.RS 4 +.Sp +Note that one usually invokes \f(CW\*(C`feedgnuplot\*(C'\fR as a part of a shell pipeline: +.Sp +.Vb 1 +\& $ write_data | feedgnuplot +.Ve +.Sp +If the user terminates this pipeline with ^C, then \fIall\fR the processes in the +pipeline receive \s-1SIGINT.\s0 This normally kills \f(CW\*(C`feedgnuplot\*(C'\fR and all its +\&\f(CW\*(C`gnuplot\*(C'\fR children, and we let this happen unless \f(CW\*(C`\-\-stream\*(C'\fR and no \f(CW\*(C`\-\-exit\*(C'\fR. +If \f(CW\*(C`\-\-stream\*(C'\fR and no \f(CW\*(C`\-\-exit\*(C'\fR, then we ignore the first ^C. The data feeder +dies, and we behave as if the input data was exhausted. A second ^C kills us +also. +.RE +.IP "\(bu" 4 +\&\f(CW\*(C`\-\-geometry\*(C'\fR +.Sp +If using X11, specifies the size, position of the plot window +.IP "\(bu" 4 +\&\f(CW\*(C`\-\-version\*(C'\fR +.Sp +Print the version and exit +.SH "RECIPES" +.IX Header "RECIPES" +.SS "Basic plotting of piped data" +.IX Subsection "Basic plotting of piped data" +.Vb 6 +\& $ seq 5 | awk \*(Aq{print 2*$1, $1*$1}\*(Aq +\& 2 1 +\& 4 4 +\& 6 9 +\& 8 16 +\& 10 25 +\& +\& $ seq 5 | awk \*(Aq{print 2*$1, $1*$1}\*(Aq | +\& feedgnuplot \-\-lines \-\-points \-\-legend 0 "data 0" \-\-title "Test plot" \-\-y2 1 +.Ve +.SS "Realtime plot of network throughput" +.IX Subsection "Realtime plot of network throughput" +Looks at wlan0 on Linux. +.PP +.Vb 3 +\& $ while true; do sleep 1; cat /proc/net/dev; done | +\& gawk \*(Aq/wlan0/ {if(b) {print $2\-b; fflush()} b=$2}\*(Aq | +\& feedgnuplot \-\-lines \-\-stream \-\-xlen 10 \-\-ylabel \*(AqBytes/sec\*(Aq \-\-xlabel seconds +.Ve +.SS "Realtime plot of battery charge in respect to time" +.IX Subsection "Realtime plot of battery charge in respect to time" +Uses the result of the \f(CW\*(C`acpi\*(C'\fR command. +.PP +.Vb 3 +\& $ while true; do acpi; sleep 15; done | +\& perl \-nE \*(AqBEGIN{ $| = 1; } /([0\-9]*)%/; say join(" ", time(), $1);\*(Aq | +\& feedgnuplot \-\-stream \-\-ymin 0 \-\-ymax 100 \-\-lines \-\-domain \-\-xlabel \*(AqTime\*(Aq \-\-timefmt \*(Aq%s\*(Aq \-\-ylabel "Battery charge (%)" +.Ve +.SS "Realtime plot of temperatures in an \s-1IBM\s0 Thinkpad" +.IX Subsection "Realtime plot of temperatures in an IBM Thinkpad" +Uses \f(CW\*(C`/proc/acpi/ibm/thermal\*(C'\fR, which reports temperatures at various locations +in a Thinkpad. +.PP +.Vb 2 +\& $ while true; do cat /proc/acpi/ibm/thermal | awk \*(Aq{$1=""; print}\*(Aq ; sleep 1; done | +\& feedgnuplot \-\-stream \-\-xlen 100 \-\-lines \-\-autolegend \-\-ymax 100 \-\-ymin 20 \-\-ylabel \*(AqTemperature (deg C)\*(Aq +.Ve +.SS "Plotting a histogram of file sizes in a directory, granular to 10MB" +.IX Subsection "Plotting a histogram of file sizes in a directory, granular to 10MB" +.Vb 4 +\& $ ls \-l | awk \*(Aq{print $5/1e6}\*(Aq | +\& feedgnuplot \-\-histogram 0 +\& \-\-binwidth 10 +\& \-\-ymin 0 \-\-xlabel \*(AqFile size (MB)\*(Aq \-\-ylabel Frequency +.Ve +.SS "Plotting a live histogram of the ping round-trip times for the past 20 seconds" +.IX Subsection "Plotting a live histogram of the ping round-trip times for the past 20 seconds" +.Vb 8 +\& $ ping \-A \-D 8.8.8.8 | +\& perl \-anE \*(AqBEGIN { $| = 1; } +\& $F[0] =~ s/[\e[\e]]//g or next; +\& $F[7] =~ s/.*=//g or next; +\& say "$F[0] $F[7]"\*(Aq | +\& feedgnuplot \-\-stream \-\-domain \-\-histogram 0 \-\-binwidth 10 \e +\& \-\-xlabel \*(AqPing round\-trip time (s)\*(Aq \e +\& \-\-ylabel Frequency \-\-xlen 20 +.Ve +.SS "Plotting points on top of an existing image" +.IX Subsection "Plotting points on top of an existing image" +This can be done with \f(CW\*(C`\-\-image\*(C'\fR: +.PP +.Vb 2 +\& $ < features_xy.data +\& feedgnuplot \-\-points \-\-domain \-\-image "image.png" +.Ve +.PP +or with \f(CW\*(C`\-\-equation\*(C'\fR: +.PP +.Vb 4 +\& $ < features_xy.data +\& feedgnuplot \-\-points \-\-domain +\& \-\-equation \*(Aq"image.png" binary filetype=auto flipy with rgbimage\*(Aq +\& \-\-set \*(Aqyrange [:] reverse\*(Aq +.Ve +.PP +The \f(CW\*(C`\-\-image\*(C'\fR invocation is a convenience wrapper for the \f(CW\*(C`\-\-equation\*(C'\fR +version. Finer control is available with \f(CW\*(C`\-\-equation\*(C'\fR. +.PP +Here an existing image is given to gnuplot verbatim, and data to plot on top of +it is interpreted by feedgnuplot as usual. \f(CW\*(C`flipy\*(C'\fR is useful here because +usually the y axis points up, but when looking at images, this is usually +reversed: the origin is the top-left pixel. +.SH "ACKNOWLEDGEMENT" +.IX Header "ACKNOWLEDGEMENT" +This program is originally based on the driveGnuPlots.pl script from +Thanassis Tsiodras. It is available from his site at + +.SH "REPOSITORY" +.IX Header "REPOSITORY" + +.SH "AUTHOR" +.IX Header "AUTHOR" +Dima Kogan, \f(CW\*(C`\*(C'\fR +.SH "LICENSE AND COPYRIGHT" +.IX Header "LICENSE AND COPYRIGHT" +Copyright 2011\-2012 Dima Kogan. +.PP +This program is free software; you can redistribute it and/or modify it +under the terms of either: the \s-1GNU\s0 General Public License as published +by the Free Software Foundation; or the Artistic License. +.PP +See http://dev.perl.org/licenses/ for more information.