chiark / gitweb /
actually check in the script
authorianmdlvl <ianmdlvl>
Tue, 23 Mar 2004 22:58:16 +0000 (22:58 +0000)
committerianmdlvl <ianmdlvl>
Tue, 23 Mar 2004 22:58:16 +0000 (22:58 +0000)
TODO
scripts/gnucap2gnuplot [new file with mode: 0755]

diff --git a/TODO b/TODO
index 8307b9bcef4122a0471f854c1ce8473b3041d23d..e67e14d73dc7cad62e0f220e285266c3e9c6282a 100644 (file)
--- a/TODO
+++ b/TODO
@@ -10,3 +10,8 @@ whatsthis no cloneandhack
 increm no cloneandhack
 whatsthis listing for zafio and dump archives
 configuration files autogenerator
+
+
+SCRIPTS
+=======
+manpage for gnucap2gnuplot
diff --git a/scripts/gnucap2gnuplot b/scripts/gnucap2gnuplot
new file mode 100755 (executable)
index 0000000..904649e
--- /dev/null
@@ -0,0 +1,189 @@
+#!/usr/bin/perl
+# This is gnucap2gnuplot, which is Copyright 2004 Ian Jackson.
+# It's a script to postprocess the output from gnucap and then run gnuplot.
+#
+# gnucap2gnuplot and its documentation are free software; you can
+# redistribute them and/or modify them under the terms of the GNU
+# General Public License as published by the Free Software Foundation;
+# either version 2, or (at your option) any later version.
+# 
+# gnucap2gnuplot and its documentation are distributed in the hope that
+# they 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.
+
+# usage:
+#    gnucap2gnuplot [<options>] input-file
+# Input file should be a .cir file (will be put through gnucap)
+#  or an output file from gnucap.
+# Produces various output files:
+#  <input-file>.gnuplots.sh                     run this to display results
+#  <input-file>,<Kind><N>.gnuplot-cmd           gnuplot script for displaying:
+#  <input-file>,<Kind><N>-<M>.gnuplot-data      gnuplot-format input data
+#  <input-file>,gnuplot-fifo                    working fifo for .gnuplots.sh
+# where
+#  <Kind> is Freq or Time (according to the type of analysis)
+#  <N>    is the count, starting at 0, of which report this is from gnucap
+#  <M>    is the individual column of Y data
+#
+# Limitations
+#
+#  Only Freq (.AC) and Time (.TRAN) plots have been tested.  If
+#   other types go wrong they can probably be fixed by adding code for
+#   them to startplot().
+#
+#  Displaying voltages and currents on the same .TRAN graph won't work
+#   well because they currently have to have the same Y scale.  This
+#   could be fixed by assigning carefully to $mmm in startplot().
+#
+#  It's a bit clumsy.
+#
+#  There's no easy way to mess with the gnuplot settings.
+
+sub fail ($) { die "gnucap2gnuplot: $_[0]\n"; }
+
+while ($ARGV[0] =~ m/^\-./) {
+    if (m/^\-\-$/) {
+       last;
+    } elsif (m/^\-g$/) {
+       $rungnucap= 1;
+    } elsif (m/^\-G$/) {
+       $rungnucap= 0;
+    } elsif (m/^\-o(.+)$/) {
+       $ofb= $1;
+    } else {
+       fail("unknown option $_\n");
+    }
+}
+
+if (@ARGV) {
+    @ARGV==1 or fail("one input file only please");
+    $if= shift @ARGV;
+    $ofb= $if unless defined $ofb;
+    $rungnucap= $if =~ m/\.cir$/i unless defined $rungnucap;
+    open STDIN, $rungnucap ? "gnucap -b $if |" : "< $if"
+       or fail("open $if: $!");
+} else {
+    fail("cannot run gnucap on stdin, run it yourself") if $rungnucap;
+    fail("you must specify -o... when running from stdin") unless defined $ofb;
+}
+
+%facttimes= qw(f 1e-15
+              p 1e-12
+              n 1e-9
+              u 1e-6
+              m 1e-3
+              K 1e3
+              Meg 1e6
+              G 1e9
+              T 1e12);
+
+$sof= "$ofb.gnuplots.sh";
+open A, "> $sof" or die $!;
+system 'chmod','+x',"$sof"; $? and die $?;
+print A <<END
+#!/bin/sh
+set -e
+fi=$ofb,gnuplot-fifo
+rm -f \$fi
+mkfifo -m 600 \$fi
+END
+    or die $!;
+sub startplot () {
+    open S, "> $ofb,$cplot.gnuplot-cmd" or die $!;
+    print S <<END
+set data style linespoints
+set y2tics autofreq
+set title '$cplot'
+END
+        or die $!;
+    $mmm[0]= 'x';
+    for ($yn=1; $yn<=$#columns; $yn++) {
+       $mmm[$yn]= 'y';
+    }
+    undef %min;
+    undef %max;
+    if ($kind eq 'Freq') {
+       for ($yn=1; $yn<=$#columns; $yn++) {
+           die unless $columns[$yn] =~ m/.*([MP])\(\d+\)$/;
+           $mmm[$yn]= 'y2' if $1 eq 'P';
+       }
+       print S "set logscale xy\n" or die $!;
+    }
+    for ($yn=1; $yn<=$#columns; $yn++) {
+       open "O$yn", "> $ofb,$cplot-$yn.gnuplot-data" or die $!;
+    }
+}
+sub endplot () {
+    return unless defined $kind;
+    foreach $mmm (keys %min) {
+       print S "set ${mmm}range [$min{$mmm}:$max{$mmm}]\n" or die $!;
+    }
+    $sep= "plot ";
+    for ($yn=1; $yn<=$#columns; $yn++) {
+       close "O$yn" or die $!;
+       $mmm[$yn] =~ m/^y2?$/ or die "$mmm[$yn]";
+       $axes= $mmm[$yn]; $axes =~ s/^y$/y1/;
+       $yoff= 1-$yn;
+       print S "$sep\\\n".
+           " '$ofb,$cplot-$yn.gnuplot-data'".
+               " axes x1$axes title '$columns[$yn]'"
+           or die $!;
+       $sep= ',';
+    }
+    print S "\n\npause -1\n" or die $!;
+    close S or die $!;
+    print A "  gnuplot $ofb,$cplot.gnuplot-cmd <\$fi &\n" or die $!;
+    $kind= undef;
+}
+
+while (<STDIN>) {
+    s/\s+$//;
+    if (m/^\#(\w+)/) {
+       endplot();
+       $kind= $1;
+       @columns= split /\s+/;
+       $cplot= $kind.($counter{$kind}++);
+       startplot();
+       next;
+    } elsif (!defined $kind) {
+       next;
+    } elsif (s/^\s+//) {
+       @numbers= split /\s+/;
+       die unless @numbers == @columns;
+       for ($yn=0; $yn<=$#columns; $yn++) {
+           $_= $numbers[$yn];
+           if (m/^(\-?\d+\.\d*)([A-Za-z]+)$/) {
+               die "factor $2" unless exists $facttimes{$2};
+               $_= $1*$facttimes{$2};
+               $numbers[$yn]= $_;
+           }
+           $mmm= $mmm[$yn];
+           $min{$mmm}= $_ unless exists($min{$mmm}) && $min{$mmm} <= $_;
+           $max{$mmm}= $_ unless exists($max{$mmm}) && $max{$mmm} >= $_;
+           if ($yn) {
+               printf {"O$yn"} "%s %s\n", $numbers[0], $_
+                   or die $!;
+           }
+       }
+    } else {
+       die "$_ ?";
+    }
+}
+die "no plots" unless defined $kind;
+endplot();
+print A <<END
+exec 3>\$fi
+printf 'hit return to quit: '
+read
+exec 3>&-
+END
+    or die $!;
+close A or die $!;
+$?=0; close STDIN; $? and fail("gnucap failed (code $?)");
+$sof= "./$sof" unless $sof =~ m,/,;
+print ": generated ; $sof\n" or die $!;