File: X15B.pm

package info (click to toggle)
libdemeter-perl 0.9.27%2Bds6-9
  • links: PTS, VCS
  • area: contrib
  • in suites: forky, sid, trixie
  • size: 74,028 kB
  • sloc: perl: 73,233; python: 2,196; makefile: 1,999; ansic: 1,368; lisp: 454; sh: 74
file content (170 lines) | stat: -rw-r--r-- 5,122 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
package Demeter::Plugins::X15B;  # -*- cperl -*-

use File::Basename;
use Moose;
extends 'Demeter::Plugins::FileType';

has '+is_binary'    => (default => 1);
has '+description'  => (default => "NSLS beamline X15B");
has '+version'      => (default => 0.1);
has '+metadata_ini' => (default => File::Spec->catfile(File::Basename::dirname($INC{'Demeter.pm'}), 'Demeter', 'share', 'xdi', 'x15b.ini'));

use Const::Fast;
const my $INIFILE => 'x15b.demeter_conf';
has '+conffile'     => (default => File::Spec->catfile(dirname($INC{'Demeter.pm'}), 'Demeter', 'Plugins', $INIFILE));
Demeter -> co -> read_config(File::Spec->catfile(dirname($INC{'Demeter.pm'}), 'Demeter', 'Plugins', $INIFILE));



#const my $ENERGY => 0;	# columns containing the
#const my $I0     => 6;	# relevant scalars
#const my $NARROW => 8;
#const my $WIDE   => 9;
#const my $TRANS  => 10;

sub is {
  my ($self) = @_;
  my $Ocircumflex = chr(212);
  my $nulls = chr(0).chr(0).chr(0);
  open D, $self->file or $self->Croak("could not open " . $self->file . " as data (X15B)\n");
  binmode D;
  my $first = <D>;
  close D;
  return 1 if ($first =~ /^$Ocircumflex$nulls/);
  return 0;
};

sub fix {
  my ($self) = @_;

  my $new = File::Spec->catfile($self->stash_folder, $self->filename);
  ($new = File::Spec->catfile($self->stash_folder, "toss")) if (length($new) > 127);

  my @columns = (Demeter->co->default("x15b", "energy") - 1,
		 Demeter->co->default("x15b", "i0")     - 1,
		 Demeter->co->default("x15b", "narrow") - 1,
		 Demeter->co->default("x15b", "wide")   - 1,
		 Demeter->co->default("x15b", "trans")  - 1);

  my @blob = ();
  my $file = $self->file;
  ## slurp the entire binary file into an array of 4-byte floats
  do {
    local $/ = undef;
    open D, $file or die "could not read $file as data (fix in X15B)\n";
    @blob = unpack("f*", <D>);
    close D
  };
  open N, ">".$new or die "could not write to $new (fix in X15B)\n";

  ## the header is mysterious, but the project name from scanedit is
  ## in there, so pull that out as text (pack and unpack process this
  ## mysterious header as text)
  my @header = ();
  foreach (1..53) {
    push @header, shift @blob;
  };
  my $string = pack("f*", @header);
  my $project = "??";
  foreach (unpack("A*", $string)) {
    $project = "$1 $2" if (/(\w+)\s+(\d+\/\d+\/\d+)/);
  };

  print N <<EOH
# X15B  project: $project
# original file: $file
# unpacked from original data as a sequence of 4-byte floats
# --------------------------------------------------------------------
#   energy           I0          narrow        wide           trans
EOH
  ;

  ## just pull out the relevant columns.  we are only reading the
  ## energy, i0, the narrow and wide windows from the Ge detector, and
  ## the transmission ion chmaber.  All other scalars are presumed
  ## uninteresting.  The indeces of these scalars in the line are
  ## defined as constants (see above).
  while (@blob) {
    shift @blob;
    my @line = ();
    foreach (1..15) {
      push @line, shift(@blob);
    };
    ## just write out the relevant lines
    printf N " %12.4f  %12.4f  %12.4f  %12.4f  %12.4f\n",
      @line[@columns];
      #@line[$ENERGY, $I0, $NARROW, $WIDE, $TRANS];
  }; # loop over rows of data

  close N;
  $self->fixed($new);
  return $new;
}

sub suggest {
  my ($self, $which) = @_;
  $which ||= 'fluorescence';
  if ($which eq 'transmission') {
    return (energy      => '$1',
	    numerator   => '$2',
	    denominator => '$5',
	    ln          =>  1,);
  } else {
    return (energy      => '$1',
	    numerator   => '$3',
	    denominator => '$2',
	    ln          =>  0,);
  };
};


__PACKAGE__->meta->make_immutable;
1;
__END__


=head1 NAME

Demeter::Plugin::X15B - NSLS X15B filetype plugin

=head1 VERSION

This documentation refers to Demeter version 0.9.26.

=head1 SYNOPSIS

This plugin directly reads the binary files written by NSLS beamline
X15B.

=head1 X15B files

At X15b there is a program called x15totxt, written in Turbo Pascal by
some dude named Tim Darling.  He kindly left behind a short
explanation the format of the X15b binary data file.  It seems that
the header is 53 4-byte numbers.  Each line of data contains 16 4 byte
numbers.  Thus this file is easily unpacked and processed in four byte
bites.

The X15B file is recognized by a a four character sequence at the
beginning of the file which consists of character 212 (capital
O-circumflex in ISO 8859) followed by three nulls (character 0).

The resulting file is a well-labeled, well-formatted column data file
in a form that will work well with Athena or virtually any other
analysis or plotting program.  The columns are: energy, the I0 ion
chamber, the narrow and wide windows on the germanium detector, and
the transmission ion chamber.

=head1 CONFIGURATION

Only the relevant columns from the original data file are passed along
to the output ascii file.  These column numbers can be configured in
the F<x15b.demeter_conf> file or via Athena's project registry
configuration interface.

=head1 AUTHOR

  Bruce Ravel, L<http://bruceravel.github.io/home>
  http://bruceravel.github.io/demeter

=cut