Skip to content
Snippets Groups Projects
pb2parti 3.07 KiB
Newer Older
#! /usr/bin/perl

$INTEGERARRAY = 1;
$DOUBLEARRAY  = 3;
$VECTORARRAY  = 5;

$PBH_MAGIC = 0xffffff98;

$swapendian = (pack("N",1) ne pack("L",1));
@attrname = ();

while($ARGV[0] =~ /^-[a]/) {
    shift, push(@attrname, shift), next if $ARGV[0] =~ /^-a/;
}


$infmt = $ARGV[0];
($min, $max, $incr) = ($ARGV[1] =~ /^(\d+)-?(\d*)%?(\d*)/);
$min = 0 unless $min ne "";
$max = $min unless $max ne "";
$incr = 1 unless $incr != 0;


$infmt = "-" if $infmt eq "" && ! -t STDIN;
$inf = sprintf($ARGV[0], $min);

unless( open(INF, $inf) ) {
    print STDERR "Can't open input file \"$inf\"\n" if $infmt;
    print STDERR <<EOF;
Usage: $0 [-a attrname] informat.pb [min-max%incr]  > out.speck
Converts partadv binary particle file(s) (with or without attribute)
to time-dependent partiview (.speck) format.
EOF
}
#if(-t STDOUT) {
#    print STDERR "Don't want to write .speck data to a terminal!\n";
#    exit(1);
#}

$attrin = scalar @attrname;
$attrout = @attrname && $attrname[0] ne "-" ? 1 : 0;

print "#! /usr/bin/env partiview\n\n";
print "datavar 0 id\n";
print "datavar 1 age\n";
print "datavar 2 $dataname\n" if $dataname;
print "\n";

$stepno = 0;
for($t = $min; $t <= $max; $t += $incr, $stepno++) {

    $inf = sprintf($infmt, $t);
    open(INF, $inf) or die "$0: $inf: cannot open input: $!, exiting";

    # Check file format: old or new?
    read(INF, $header, 3*4);

    ($magicbe) = unpack("N", $header);
    ($magicle) = unpack("V", $header);
    if($magicbe == $PBH_MAGIC) {
	($magic, $dataoff, $attrin) = unpack("N*", $header);
	$inswap = $swapendian;
    } elsif($magicle == $PBH_MAGIC) {
	($magic, $dataoff, $attrin) = unpack("V*", $header);
	$inswap = !$swapendian;
    } else {
	$dataoff = 0;
    }
    if($dataoff > 0) {
	read(INF, $attrstrs, $dataoff-3*4);
	@attrname = ( split(/\0/, $attrstrs) )[ 0..$attrin-1 ];
	if($t == $min) {
	    for($i = 0; $i < @attrname; $i++) {
		printf "datavar %d %s\n", $i+2, $attrname[$i];
	    }
	}
	$preload = "";
    } else {
	$preload = $header;
    }
    $readunit = (4 + $attrin) * 4;

    #seek(INF, $dataoff, 0);

    $len = ( stat($inf) )[7];
    if($len < 0) {
	print STDERR "$0: input file $inf must be a real file\n";
	exit(1);
    }
    if(tell(INF) && ($len-$dataoff) % $readunit != 0) {
	print STDERR "File $inf is $len bytes long, not a multiple of $readunit.  Need -a parameter?\n";
	exit(1);
    }

    $attrfmt = " %.6g" x $attrin;

    print "\ndatatime $stepno # $t\n\n";
    if($preload ne "") {
	if(read(INF, $rec, $readunit-length($preload)) < $readunit-length($preload)) {
	    print STDERR "Error reading first pcle\n";
	    exit(1);
	}
	$rec = $preload . $rec;
	&putrec;
    }
    while(read(INF, $rec, $readunit) == $readunit) {
	&putrec;
    }
}

sub putrec {
    $rec = pack("N*", unpack("V*", $rec)) if $inswap;
    ($id, @v) = unpack("Lf*", $rec);
    @p = splice(@v, 0, 3);
    $born[$id] = $t unless defined($born[$id]);
    printf "%.8g %.8g %.8g %d %.3g", @p, $id, $t - $born[$id];
    printf $attrfmt, @v if @attrname;
    print "\n";
}

sub dist {
    my($x) = $_[3]-$_[0];
    my($y) = $_[4]-$_[1];
    my($z) = $_[5]-$_[2];
    sqrt($x*$x + $y*$y + $z*$z);
}