in reply to graphic a segy file
Unless TkZinc is expecting you to pass data in PDL form (which from a quick scan of the docs, it isn't), your use of PDL here is doing nothing to speed up your program. In fact, it is probably slowing it down by forcing the conversion of the float values you are setting into your PDL arrays into PDL form which will then be converted back when TkZinc accesses them.
Ie. If you use ordinary perl arrays inplace of the PDL arrays, your code will probably run (slightly) faster.
Most of the time in your script is being consumed by the routine conv_bit_string_2_ibm32float(). Whilst this routine does correctly (kind of) convert IBM32 floats to IEEE native form, it is not very well coded.
$ibm_float = (( $sign_bit )*( 16**( $exponent - 64 ) ) * $fraction + )/3000;
(That had me stumped for a while! :)
If you need to scale the data, this should be done outside the conversion routine.
Doing this outside the routine makes no sense. It should be a part of the sub.
$aux = $_[0]; $aux = shift;
Putting that together with a few other changes that should improve the performance, I came up with this which does the same job somewhat more quickly:
sub conv_bit_string_2_ibm32float { my( $first_digit, $bin_exponent, $bin_fraction ) = unpack 'A1A7A24', $_[ 0 ]; my $sign_bit = ( -1 ) ** $first_digit; my $exponent = bin2dec( $bin_exponent ); my $place_holder = -1; my $fraction = 0; foreach my $bit ( split '', $bin_fraction ) { $fraction += $bit * ( 2 ** $place_holder ); $place_holder += -1; } my $ibm_float = ( ($sign_bit ) * ( 16 ** ( $exponent - 64 ) ) * $f +raction ); return $ibm_float; } sub bin2dec { return unpack( "N", pack( "B32", substr( "0" x 32 . shift, -32 )) +); }
Using normal Perl arrays and the above routine may improve your performance somewhat, but doing the conversion this way is always going to be slow.
If you are plotting seismic data (?) and dealing with large volumes of it, then you would be well advised to pre-convert the IBM32 floats in your SEGY files in bulk before plotting your your data. Pre-conversion would reduce your plotting time immensly.
There is almost certainly a utility available to convert ibm32 segy format files to IEEE float format segy files.
A google turned up tito (from the GU toolkit) which appears to do the conversion, but I didn't look further at it to see if it was public domain. There are probably others around also.
However, if you cannot locate a conversion utility, it would be fairly simple to code the above conversion routine using Inline::C such that you pass it a raw string that you read from the file and a count, and it would return you a perl array of native floats suitable for passing directly to TkZinc. That would run a couple of orders of magnitude more quickly than the pure perl conversion routine above.
It would still make sense to perform the conversion as a batch process rather than whilst plotting.
Speak up if you would like some help with that. There are many people here quite adept at writing Inline::C routines.
Hope that clarifies a few things.
|
|---|