
package cal_pipe2;

require Exporter;

@ISA      = qw(Exporter);
@EXPORT   = qw(cal_point);

#use strict;

sub cal_point {

  # Get arguments passed from cal_pipe2.pm
  my ($file, $hv, $c) = @_;
  my %head_vals = %$hv;
  my %cmds = %$c;

  my ($ir_state, $vis_state, $ir_power_state, $vis_power_state, $line);
  my ($core_item_type, $power_state_flag, $smpl, $bnd, $ln, $core_name);
  my ($instrument_mode_id, $file2, $path, $file2_nopath, $fileCM, $temp);
  my ($file_nopath, $ff, $cmd, $sat, $ir_exp, $vis_exp);
  my ($start_sample, $start_line, $sampling_mode, $ir_sampling_mode);
  my ($vis_sampling_mode, $key, $background_sampling_mode);
  my ($vis_back_samp_mode, $ir_back_samp_mode, $gain_mode);
  my ($vis_gain_mode, $ir_gain_mode, $dsp1, $dsp2, $dsp3, $dsp4);
  my ($doperf, $doflat, $do_specific_energy, $garbage, $spkfil);
  my ($vissm, $vres, $vexp, $dovisdark, $fib, $sef, $ssf);
  my ($compressor_id, $compid);

  my $idldir = $ENV{IDL_DIR};

  # Find the core cube name.
  ($path,$file_nopath) = $file =~ /(.*\/)(.*)/;
  ($core_name) = $file =~ /.*\/[A-Z,a-z]*([_\d]*).*/;
  print("cube core_name = $core_name\n");

  # The state flags indicate which instruments are turned on.
  # We assume that at least one instrument is on since we have a cube!
  my $ir_state = 1;
  my $vis_state = 1;
  if ($head_vals{ir_power_state} eq "OFF") { $ir_state = 0; }
  if ($head_vals{vis_power_state} eq "OFF") { $vis_state = 0; }

  # Run 'cube_prep' on the cube.
  $file2 = $path . $core_name;
  ($path,$file2_nopath) = $file2 =~ /(.*\/)(.*)/;
  $fileCM = $path . "CM_" . $file2_nopath . ".cub";

  # cube_prep adds calibration keyword/values pairs to the header,
  # looks up and translates the back plane data, and swaps bytes if
  # needed.
  print ("blarg = $head_vals{core_item_type}\n");
  if ($head_vals{core_item_type} eq "SUN_INTEGER") {
    # Swap bytes.
    $cmd = "$ENV{caldir}/software/bin/cube_prep $file $fileCM s\n";
    print ("$cmd");
    system ("$cmd");
  } elsif ($head_vals{core_item_type} eq "PC_INTEGER") {
    # Don't swap bytes.
    $cmd = "$ENV{caldir}/software/bin/cube_prep $file $fileCM\n";
    print ("$cmd");
    system ("$cmd");
  } else {
    print("cube core_item_type is strange, skipping...\n");
    next;
  }

  # If the compressor was turned off, we need to subtract
  # the IR background values from the cube.
  $temp = "tempcb.cub";
  $garbage = "garbage_data";
  $compid  = $head_vals{"compressor_id"};
  print("compid = $compid\n");
  if ($compid == 'N/A') {
    $cmd = "$ENV{caldir}/software/bin/ir_bg_sub $fileCM $temp\n";
    print("$cmd");
    system("$cmd");
    system("mv $temp $fileCM");

  }

  # Run 'mark_saturated' on the 'CM_' file.  This program adds
  # the background back into each pixel and checks to see if
  # it is greater than or equal to 4095.  If it is, it marks it
  # as saturated (pixel value set to -32765).
  $temp = "tempcb.cub";
  $garbage = "garbage_data";
  $sat  = $cmds{"mark_saturated"};
  if ($sat eq "yes") {
    $cmd = "$ENV{caldir}/software/bin/mark_saturated $fileCM $temp\n";
    print("$cmd");
    system("$cmd");
    system("mv $temp $fileCM");

    # Update the header to show that this step has been run.
    $cmd = "labels from=$fileCM" .
	   "  list=SUMMARY" .
	   "  dest=FILE" .
	   "  listfile=listfile" .
	   "  grpnam=CALIBRATION" .
	   "  keyword=SET_SATURATED" .
	   "  keyvalue=YES" .
	   "  keytype=STRING";
    system($cmd);
    system("rm listfile.lis");
  }

  # Construct a command file for "make_dark" containing the command
  # to make_dark (an IDL routine) with the appropriate arguments.
  $vissm = $head_vals{vis_sampling_mode};
  if ($vissm eq "HIGH" || $vissm eq "HI-RES") {
    $vres = "hi";
  } else {
    $vres = "lo";
  }
  $vexp = $head_vals{'vis_exp'};

  system("rm md_cmd");
  open(MD_CMD, "> md_cmd") or die "Can't open md_cmd: $!\n";
  print MD_CMD "restore, \"$ENV{caldir}/software/bin/make_dark.sav\"\n";
  if ($head_vals{ssf} eq "ON") {
    print MD_CMD "make_dark,\"",$vres,"\",",$vexp,",\"tmp_vis_dark.cub,specsum=\"yes\"\"\n";
  } else {
    print MD_CMD "make_dark,\"",$vres,"\",",$vexp,",\"tmp_vis_dark.cub\"\n";
  }
  print MD_CMD "exit\n";
  close (MD_CMD);

  print ("idl md_cmd\n");
  system("$idldir/bin/idl md_cmd");

  # Remove the dark from the VIS data
  my $dovisdark = $cmds{"vis_background"};
  my $vbsm = $head_vals{'vis_back_samp_mode'};
  if ($dovisdark eq "yes" and $vbsm = "ZERO_SUB") {
    if ($vis_state) {
      print("dark_vis.pl $fileCM $temp head_vals\n");
      dark_vis ($fileCM, $temp, %head_vals);
      system("mv $temp $fileCM");
    }
  }
  system("rm tmp_vis_dark.cub");
  system("rm md_cmd");

  # Transpose the cube to make some things run faster.
  $cmd = "transpose from=$fileCM to=$temp order=BSQ\n";
  print("$cmd");
  system($cmd);
  system("mv $temp $fileCM");

  # Flat field the IR cube then flat field the VIS cube (if wanted).
  my $doirflat = $cmds{"ir_flat_field"};
  if ($doirflat eq "yes") {
    if ($ir_state) {
      print("flat_ir2 $fileCM $temp head_vals\n");
      flat_ir2 ($fileCM, $temp, %head_vals);
      system("mv $temp $fileCM");
    }
  }

  my $dovisflat = $cmds{"vis_flat_field"};
  if ($dovisflat eq "yes") {
    if ($vis_state) {
      print("flat_vis2.pl $fileCM $temp head_vals\n");
      flat_vis2 ($fileCM, $temp, %head_vals);
      system("mv $temp $fileCM");
    }
  }

  # This step removes the performance model, divides by the exposure time,
  # and then converts the resulting electrons/second to ergs/sec/spectel.
  my $to_specific_energy = $cmds{"to_specific_energy"};
  if ($to_specific_energy eq "yes") {
    print("specific_energy $fileCM $temp head_vals\n");
    specific_energy($fileCM, $temp, %head_vals);
    system("mv $temp $fileCM");

    # Change CORE_NAME to SPECIFIC_ENERGY and CORE_UNIT to ERGS_PER_SECOND
    $cmd = "labels from=$fileCM" .
	   " list=NONE" .
	   " dest=FILE" .
	   " listfile=listfile" .
	   " objtyp=QUBE" .
	   " keyword=CORE_NAME" .
	   " keyvalue=SPECIFIC_ENERGY" .
	   " keytype=LITERAL";
    print("$cmd\n");
    system($cmd);
    system("rm listfile.lis");

    $cmd = "labels" .
	   " from=$fileCM" .
	   " list=NONE" .
	   " dest=FILE" .
	   " listfile=listfile" .
	   " objtyp=QUBE" .
	   " keyword=CORE_UNIT" .
	   " keyvalue=ERGS_PER_SECOND" .
	   " keytype=LITERAL";
    print("$cmd\n");
    system($cmd);
    system("rm listfile.lis");
  }

  # Converting to I/F involves dividing by the solar spectrum at
  # the radius from the sun where the data was taken.  This involves
  # using the solar spectrum at one AU and the distance in AU at the
  # observation point.
  my $to_I_over_F = $cmds{"to_I_over_F"};
  my $times_pi = $cmds{"times_pi"};
  if ($to_I_over_F eq "yes" and $to_specific_energy eq "yes") {
    print("solar_remove.pl $fileCM $temp $times_pi head_vals\n");
    solar_remove($fileCM, $temp, $times_pi, %head_vals);
    system("mv $temp $fileCM");

    # Change CORE_NAME to I_OVER_F and CORE_UNIT to DIMENSIONLESS
    $cmd = "labels from=$fileCM" .
	   " list=NONE" .
	   " dest=FILE" .
	   " listfile=listfile" .
	   " objtyp=QUBE" .
	   " keyword=CORE_NAME" .
	   " keyvalue=I_OVER_F" .
	   " keytype=LITERAL";
    print("$cmd\n");
    system($cmd);
    system("rm listfile.lis");

    $cmd = "labels" .
	   " from=$fileCM" .
	   " list=NONE" .
	   " dest=FILE" .
	   " listfile=listfile" .
	   " objtyp=QUBE" .
	   " keyword=CORE_UNIT" .
	   " keyvalue=DIMENSIONLESS" .
	   " keytype=LITERAL";
    print("$cmd\n");
    system($cmd);
    system("rm listfile.lis");
  }

  system("rm $fileCM" . ".tmp\n");

  my $splitcubes    = $cmds{"splitcubes"};
  my $backplanes    = $cmds{"backplanes"};
  my $keepcomposite = $cmds{"keepcomposite"};

  # Make sure we copy the timing backplanes from the original
  # cube back onto the output cube here.  The backplanes were
  # lost during execution of FX or RATIO or somewhere.
  # we must swap the bytes of the original cube into a temp cube first.
  my $tempcube = "TempCub.cub";
  $cmd = "$ENV{caldir}/software/bin/cube_prep $file $tempcube s\n";
  print ("$cmd");
  system ("$cmd");

  # bandcopy
  $cmd = "bandcopy" .
         " from=$tempcube" .
         " sfrom='\"::\"'" .
         " to=$fileCM" .
         " iband=0" .
         " oband=0" .
         " ibcknam=SLICE_TIME_SECONDS" .
         " obcknam=SLICE_TIME_SECONDS";
  print("$cmd\n");
  system($cmd);

  $cmd = "bandcopy" .
         " from=$tempcube" .
         " sfrom='\"::\"'" .
         " to=$fileCM" .
         " iband=0" .
         " oband=0" .
         " ibcknam=SLICE_TIME_TICKS" .
         " obcknam=SLICE_TIME_TICKS";
  print("$cmd\n");
  system($cmd);

  system("rm $tempcube\n");


  # Transpose the cube back to BIL.
  $cmd = "transpose from=$fileCM to=$temp order=BIL\n";
  print("$cmd");
  system($cmd);
  system("mv $temp $fileCM");

}   # end of subroutine.
