UIST – Correct Non-Linearity

UIST – Correct Non-Linearity

# -*-perl-*-

=head1 NAME

_CORRECT_NONLINEARITY_ -- Corrects the raw data for detector
non-linearity.

=head1 DESCRIPTION

This primitive is used to correct UIST frames for non-linearity. It
only operates on data taken after 20070501.

UIST's detector is non-linear in different ways depending on the
waveform used and the observed count.

For non-thermal data, the correction factor is:

 y = ( 1.7929E-14 * x^3 ) - ( 1.9544E-10 * x^2 ) + ( 6.5558E-6 * x ) + 0.98657

for data where the counts are between 750 and 20000 ADUs.

For thermal data, the correction factors are:

 y = ( 3.6058E-27 * x^6 ) - (4.1373E-22* x^5) + ( 1.8632E-17 * x^4 ) - ( 4.1209E-13 * x^3 ) +
     ( 4.762E-9 * x^2 ) - ( 2.353E-5 * x ) + 1.0294

for data where the counts are between 890 and 36000 ADUs.

This correction factor is multiplied by the observed count to obtain
the corrected value in each pixel.

=head1 NOTES

=over 4

=item *

This primitive is suitable for UIST in imaging mode.

=back

=head1 AUTHORS

Brad Cavanagh <b.cavanagh@jach.hawaii.edu>

=head1 COPYRIGHT

Copyright (C) 2007 Science and Technology Facilities Council.  All
Rights Reserved.

=cut

# Only run if the UT date is after 20070501 and we haven't corrected
# yet.
if( $Frm->hdr( "ORACTIME" ) > 20070501 && ! defined( $Frm->uhdr( "NONLINEARITY_CORRECTED" ) ) ) {

  # Set the filenames.
  my( $in, $out ) = $Frm->inout( "_nl" );

  # Check the waveform. If it's thermal, then we have to use a separate
  # set of correction equations.
  my $waveform = $Frm->hdr( "WAVEFORM" );

  if( $waveform =~ /thermal/i ) {

    orac_print "Applying thermal non-linearity corrections.\n";

    # Thermal waveform.
    my $lo1 = 890;
    my $hi1 = 36000;

    # Threshold the first batch into a temporary file.
    my $tmp1 = new ORAC::TempFile;
    my $tmp1file = $tmp1->file;
    my $params = "in=$in out=$tmp1file thrlo=$lo1 thrhi=$hi1 newlo=bad newhi=bad";
    $Mon{'kappa_mon'}->obeyw( "thresh", "$params" );

    # Run MATHS.
    my $tmp2 = new ORAC::TempFile;
    my $tmp2file = $tmp2->file;
    $params = "exp='IA*(1.0*(3.6058E-27*IA**6)-(4.1373E-22*IA**5)+(1.8632E-17*IA**4)-(4.1209E-13*IA**3)+(4.762E-9*IA**2)-(2.353E-5*IA)+1.0294)' out=$tmp2file ia=$tmp1file";
    $Mon{'kappa_mon'}->obeyw( "maths", "$params" );

    # Paste them onto the input file.
    $params = "in=$in p1=$tmp2file out=$out";
    $Mon{'kappa_mon'}->obeyw( "paste", "$params" );

  } else {

    orac_print "Applying non-thermal non-linearity corrections.\n";

    # Non-thermal waveform.
    my $lo = 750;
    my $hi = 20000;

    # Threshold into a temporary file.
    my $tmp1 = new ORAC::TempFile;
    my $tmp1file = $tmp1->file;
    my $params = "in=$in out=$tmp1file thrlo=$lo thrhi=$hi newlo=bad newhi=bad";
    $Mon{'kappa_mon'}->obeyw( "thresh", "$params" );

    # Run MATHS on the thresholded file.
    my $tmp2 = new ORAC::TempFile;
    my $tmp2file = $tmp2->file;
    $params = "exp='IA*((1.7929E-14*IA**3)-(1.9544E-10*IA**2)+(6.5558E-6*IA)+0.98657)' out=$tmp2file ia=$tmp1file";
    $Mon{'kappa_mon'}->obeyw( "maths", "$params" );

    # Paste this output onto the input file. The bad pixels in the
    # linearity-corrected file will allow the base image's pixels to
    # come through.
    $params = "in=$in p1=$tmp2file out=$out";
    $Mon{'kappa_mon'}->obeyw( "paste", "$params" );

  }

  # Report to the user.
  orac_print "$in to $out: Detector non-linearity corrected.\n";

  # Update the frame object.
  $Frm->uhdr( "NONLINEARITY_CORRECTED", 1 );
  $Frm->file( $out );

  # Display, if necessary.
  _DISPLAY_FRAME_IMAGE_

  # Tidy-up output.
  orac_print "\n";

}