Index: /trunk/ippScripts/scripts/detrend_norm_exp.pl
===================================================================
--- /trunk/ippScripts/scripts/detrend_norm_exp.pl	(revision 9135)
+++ /trunk/ippScripts/scripts/detrend_norm_exp.pl	(revision 9135)
@@ -0,0 +1,138 @@
+#!/usr/bin/env perl
+
+use warnings;
+use strict;
+
+use vars qw( $VERSION );
+$VERSION = '0.01';
+
+use IPC::Cmd qw( can_run run );
+use PS::IPP::Metadata::Config;
+use PS::IPP::Metadata::List qw( parse_md_list );
+use Statistics::Descriptive;
+
+use Getopt::Long qw( GetOptions :config auto_help auto_version gnu_getopt );
+use Pod::Usage qw( pod2usage );
+
+my ($det_id, $iter, $det_type, $camera, $no_update);
+GetOptions(
+    'det_id|d=s'        => \$det_id,
+    'iteration|i=s'     => \$iter,
+    'camera|c=s'        => \$camera,
+    'det_type|t=s'      => \$det_type,
+    'no-update'         => \$no_update
+) or pod2usage( 2 );
+
+pod2usage( -msg => "Unknown option: @ARGV", -exitval => 2 ) if @ARGV;
+pod2usage(
+    -msg => "Required options: --det_id --iteration --camera --det_type",
+    -exitval => 3,
+) unless defined $det_id
+     and defined $iteration
+     and defined $camera
+     and defined $det_type;
+
+use constant RECIPE1 => 'PPIMAGE_J1'; # Recipe to use for ppImage to make JPEGs
+use constant RECIPE2 => 'PPIMAGE_J2'; # Recipe to use for ppImage to make JPEGs
+
+
+# Look for programs we need
+my $missing_tools;
+my $dettool = can_run('dettool') or (warn "Can't find dettool" and $missing_tools = 1);
+my $ppImage = can_run('ppImage') or (warn "Can't find ppImage" and $missing_tools = 1);
+die "Can't find required tools.\n" if $missing_tools;
+
+my $mdcParser = PS::IPP::Metadata::Config->new;	# Parser for metadata config files
+
+# Get list of component files
+my $files;			# Array of component files
+{
+    my $command = "$dettool -normalizedimfile -det_id $det_id -iteration $iter"; # Command to run
+    my ( $success, $error_code, $full_buf, $stdout_buf, $stderr_buf ) =
+	run(command => $command, verbose => 1);
+    die "Unable to perform dettool -normalizedimfile: $error_code\n" if not $success;
+    my $metadata = $mdcParser->parse(join "", @$stdout_buf) 
+        or die "unable to parse metadata config doc";
+    $files = parse_md_list($metadata);
+}
+
+# Gather the statistics
+my ($bg, $bg_stdev, $bg_mean_stdev); # The statistics triplet
+{
+    my @backgrounds;		# Array of backgrounds in each component
+    my @stdevs;			# Array of standard deviations in each component
+    foreach my $file (@$files) {
+	die "Unable to find class id\n" unless defined $file->{class_id};
+	my $class_id = $file->{class_id};
+	die "Unable to find bg for class_id=$class_id\n" unless defined $file->{bg};
+	die "Unable to find bg_mean_stdev for class_id=$class_id\n" unless defined $file->{bg_mean_stdev};
+	push @backgrounds, $file->{bg};
+	push @stdevs, $file->{bg_mean_stdev};
+    }
+
+    {
+	my $stats = Statistics::Descriptive::Sparse->new; # Statistics calculator
+	$stats->add_data(@backgrounds);
+	$bg = $stats->mean();
+	if (scalar @backgrounds == 1) {
+	    $bg_stdev = 0.0;
+	} else {
+	    $bg_stdev = $stats->standard_deviation();
+	}
+    }
+    {
+	my $stats = Statistics::Descriptive::Sparse->new; # Statistics calculator
+	$stats->add_data(@stdevs);
+	$bg_mean_stdev = $stats->mean();
+    }
+}
+
+# Generate the file list, and get the statistics
+my $outputRoot = $camera . '.' . $detType . '.norm.' . $detId . '.' . $iter; # Root output name
+my $list1Name = $outputRoot . '.b1.list'; # Name for the input file list for binning 1
+my $list2Name = $outputRoot . '.b2.list'; # Name for the input file list for binning 2
+my @means;			# Array of means
+my @stdevs;			# Array of stdevs
+open my $list1File, '>' . $list1Name;
+open my $list2File, '>' . $list2Name;
+foreach my $file (@$files) {
+    print $list1File $file->{b1_uri} . "\n";
+    print $list2File $file->{b2_uri} . "\n";
+    push @means, $file->{bg};
+    push @stdevs, $file->{bg_stdev};
+}
+close $list1File;
+close $list2File;
+
+# Output products --- need to synch with the camera configuration!
+my $jpeg1Name = $outputRoot . ".b1.jpg"; # Binned JPEG #1
+my $jpeg2Name = $outputRoot . ".b2.jpg"; # Binned JPEG #2
+
+# Make the jpeg for binning 1
+{
+    my $command = "$ppImage -list $list1Name $outputRoot -recipe PPIMAGE " . RECIPE1; # Command to run
+    my ( $success, $error_code, $full_buf, $stdout_buf, $stderr_buf ) =
+	run(command => $command, verbose => 1);
+    die "Unable to find expected output file: $jpeg1Name\n" if not -f $jpeg1Name;
+}
+
+# Make the jpeg for binning 2
+{
+    my $command = "$ppImage -list $list2Name $outputRoot -recipe PPIMAGE " . RECIPE2; # Command to run
+    my ( $success, $error_code, $full_buf, $stdout_buf, $stderr_buf ) =
+	run(command => $command, verbose => 1);
+    die "Unable to find expected output file: $jpeg2Name\n" if not -f $jpeg2Name;
+}
+
+# Add the result into the database
+unless ($no_update) {
+    my $command = "$dettool -addnormexp -det_id $det_id -iteration $iter " .
+	"-recip " . RECIPE1() . "," . RECIPE2() . " -b1_uri $jpeg1Name -b2_uri $jpeg2Name " .
+	"-bg $bg -bg_stdev $bg_stdev -bg_mean_stdev $bg_mean_stdev"; # Command to run
+    my ( $success, $error_code, $full_buf, $stdout_buf, $stderr_buf ) =
+	run(command => $command, verbose => 1);
+    die "Unable to perform dettool -addnormexp: $error_code\n" if not $success;
+}
+
+
+__END__
