# Perform a photometric solution for an entire night (or some large
#   set of raw instrumental data files).  
#
# MWR 11/27/2000
#
# Remove the "input_dir", since we use same directory for input and output
#   MWR  1/28/2001
#
# Modify "get_collated_files" to use new convention for collated file names
#   Also modify "create_output_stem" to use new convention.
#   MWR  4/16/2001
#
# Add the new "mode" option, with "noextinct" value, to the command
#   string used to run the "photom" program.  This is required for
#   photom version 0.4.
#   MWR  11/26/2002
#
# Add support for the new "fixk" parameter, which allows one to correct
#   for differential extinction across an image.
#   MWR  02/16/2003
#
# We now save two additional pieces of information in the "make_list.out"
#   file: the zeropoint and colorterm for each frame.
#   Requires new proc, "save_coeffs".
#   Also, when we've finished with all the "photom" processing,
#   make a copy of the "make_list.out" file, giving it a file name stem
#   identical to the .cal file, and an extension ".list".  
#   In other words, copy
#    
#        make_list.out   -->   Mhra2604797.list
#
#   MWR  04/11/2003
#
# Now use "get_photom_refcat_name" instead of "get_refcat_name"
#    because we now support two different reference catalogs.
#   MWR  04/18/2003
#
# Added a private namespace, "Photom", which serves to hold
#    the stem of the "archivable" files.  For the example described above,
#    the stem will be set to "Mhra2604797". 
#    We need this to create the name for the list-of-all-parameters,
#    so it will match the name of the .cal and .list files.
#   MWR  04/24/2003
#
# Modified "get_passband_columns" so that it checks to make sure that
#    it was able to figure out the proper columns for each passband
#    in the .clt files.  If it fails, it now will print an error
#    message and return with error code.
#   MWR  05/14/2003
#
# Modify "get_collated_files" so that it checks each candidate .clt file
#    to see if it's empty; if so, it will be discarded.  Only .clt files
#    with data are included in the arg list for the "photom" program.
#    Empty .clt files can cause problems ...
#   MWR  05/15/2003
#
# Added support for "photom_orphans" parameter, which controls the
#    new "orphans=" command-line option for photom.  If set to 1,
#    we include single-passband detections in output, using
#    a color term of zero.
#   MWR  03/26/2005



if { [catch { set debug } ] != 0 } {
  set debug 2
}

# contains source for the "get_param" proc
source param.tcl


#############################################################################
# PROCEDURE: photom
#
# DESCRIPTION: prepare everything required to run the 'photom' program
#              on the data files full of raw, instrumental magnitudes.
#              The result will be a photometric solution for the night
#              (on in each filter), and a set of calibrated output files
#              (one per filter).
#
# RETURNS:
#     0                           if all goes well
#     1                           if a serious error occurs
#
proc photom { param_file } {
  global debug

  if { $debug > 0 } {
    puts "entering photom"
  }

  if { [file exists $param_file] != 1 } {
    puts "photom: can't find param file $param_file"
    return 1
  }

  set output_dir       [get_param $param_file "output_dir"]
  set photom_exe       [get_param $param_file "photom_exe"]
  set debug_file       [get_param $param_file "debug_file"]
  set ref_ra_col       [get_param $param_file "ref_ra_col"]
  set ref_dec_col      [get_param $param_file "ref_dec_col"]
  set ref_V_col        [get_param $param_file "ref_V_col"]
  set ref_I_col        [get_param $param_file "ref_I_col"]
  set ref_matchrad     [get_param $param_file "ref_matchrad"]
  set col_ra_col       [get_param $param_file "col_ra_col"]
  set col_dec_col      [get_param $param_file "col_dec_col"]
  set col_jd_col       [get_param $param_file "col_jd_col"]
  set col_air_col      [get_param $param_file "col_air_col"]
  set col_triplet_col  [get_param $param_file "col_triplet_col"]
  set col_quality_col  [get_param $param_file "col_quality_col"]
  set filt_pairs       [get_param $param_file "filt_pairs"]
  set fixk             [get_param $param_file "fixk"]
  set photom_orphans   [get_param $param_file "photom_orphans"]

  # Get the name of the directory in which the "photom" program lives,
  #   and prepend it to the executable's name
  set photom_dir [get_directory "photom_dir"]
  set photom_exe $photom_dir/$photom_exe

  # we get the name of the mini-catalog with astrometric reference stars
  #   by calling a special function, rather than using a parameter,
  #   because the name is set with a parameter in ANOTHER param file
  set refcat_name [get_photom_refcat_name]

  # get a list of all possible raw instrumental magnitude files which
  #   have been produced by the "collate" program
  if { [get_collated_files $output_dir collated_list] != 0 } {
    puts stderr "photom: get_collated_files fails"
    return 1
  }
  if { $debug > 2 } {
    puts "photom: collated_list is $collated_list"
  }

  # get a list of all possible filters we need to calibrate
  if { [get_list_info filter_list "filter"] != 0 } {
    puts stderr "photom: get_list_info fails on 'filter'"
    return 1
  }


  # Now we prepare to call the external "photom" program, which 
  #   will perform photometric solutions in all appropriate
  #   passbands.
  set primary_filter "V"
  set secondary_filter "I"



    # figure out the proper columns to use in the collated output files;
    #   that is, figure out which columns contain the primary passband data,
    #   and which the secondary passband data.
    #   Perform a check to see that all the files have similar formats.
    if { [get_passband_columns $primary_filter $secondary_filter \
                               $collated_list $col_triplet_col \
			       pri_filt_col pri_mag_col pri_magerr_col \
			       sec_filt_col sec_mag_col sec_magerr_col] != 0 } {
      puts stderr "photom: get_passband_columns fails"
      return 1
    }
    if { $debug > 2 } {
      puts "photom: pri cols $pri_filt_col $pri_mag_col $pri_magerr_col "
      puts "photom: sec cols $sec_filt_col $sec_mag_col $sec_magerr_col "
    }


    # must figure out the stem of the output filenames, and save it
    #   for future reference
    if { [create_output_stem $output_dir $collated_list \
                             output_stem ] != 0 } {
      puts stderr "photom: create_output_stem fails"
      return 1
    }
    if { [init_photom_stem $output_stem] != 0 } {
      puts stderr "photom: init_photom_stem fails"
      return 1
    }


    # okay, we're ready to call the program which performs photometric
    #   solution and calibration!
    if { [run_photom $output_dir $refcat_name $ref_ra_col $ref_dec_col \
                             $ref_V_col $ref_I_col $ref_matchrad \
                             $collated_list \
			     $col_ra_col $col_dec_col $col_jd_col \
			     $col_air_col $col_quality_col \
			     $pri_filt_col $pri_mag_col $pri_magerr_col \
			     $sec_filt_col $sec_mag_col $sec_magerr_col \
                             $primary_filter $secondary_filter \
              $fixk $photom_orphans \
			     $photom_exe $output_stem $debug_file ] != 0 } {
       puts stderr "photom: run_photom fails"
       return 1
    }


    # now, try to look through the .coeff file (one of the outputs of the
    #   photom program), which contains the zeropoint and color term
    #   of the solution for each image.  
    #   Write this information into the file list
    if { [save_coeffs $output_dir $output_stem  $collated_list] != 0 } {
      puts stderr "photom: save_coeffs fails for stem $output_stem "
      puts stderr "photom:    but continuing with processing anyway"
    }


    # Make a copy of the "make_list.out" file -- which now contains
    #   oodles of good information for each image, including photometric
    #   zeropoint and color term -- which has a name similar to the 
    #   .cal file.
    if { [copy_list_file $output_dir $output_stem] != 0 } {
      puts stderr "photom: copy_list_file fails for $output_stem "
      puts stderr "photom:    but continuing with processing anyway "
    }


  return 0
}



##############################################################################
# PROCEDURE: get_collated_files
#
# DESCRIPTION: Given a directory name, find all the files in that directory
#              which were produced by the "collate" program.  These files
#              have names which look like:
#
# ---------------------- new convetion, Disk Set 17 and later -------------
#                        Mhra1992737.clt
#              where
#                    M            is alwaus the first character
#                    h            is the observatory code
#                    ra1992737    is some stuff I don't understand
#                    .clt         is the extension
#
# ---------------------- old convention, Disk Set 16 and earlier ----------
#                        M1234.567
#            
#              where 
#                    M            is always the first character
#                    1234         is integer part of the modified Julian Date
#                    567          is fractional Julian Date of image
# -------------------------------------------------------------------------
#
#
#              If any such files are found, their names are placed in the
#              'collated_list' argument (including the directory prefix).
# 
# RETURNS:
#     0                    if all goes well
#     1                    if an error occurs (but not if no files are found)
#
proc get_collated_files { output_dir collated_list } {
  global debug
  upvar $collated_list col_list

  if { $debug > 1 } {
    puts "entering get_collated_files"
  }

  set candidate_list [glob $output_dir/M\[A-Za-z\]*.clt ]

  # check each of the candidates to see if it has any data inside.
  #   Discard any empty files
  set col_list {}
  foreach candidate $candidate_list {
    if { [catch { set wc_output [exec wc $candidate] } ] != 0 } {
      puts stderr "get_collated_files: $candidate fails wc? skip it"
      continue
    }
    if { $debug > 0 } {
      puts "get_collated_files: $candidate has wc ..$wc_output.. "
    } 
    set nlines [lindex $wc_output 0]
    if { $nlines < 1 } {
      puts stderr "get_collated_files: $candidate is empty ... skipping"
    } else { 
      if { $debug > 0 } {
        puts "get_collated_files: $candidate is okay "
      }
      lappend col_list $candidate
      if { $debug > 0 } {
        puts "get_collated_files: list is now $col_list"
      }
    }
  }
  
  return 0
}



##############################################################################
# PROCEDURE: get_secondary_filter
#
# DESCRIPTION: Given a primary filter name, and a list of pairs of 
#              primary-secondary filters, look for the secondary filter
#              for the given primary.  If found, return its name.
# 
# RETURNS:
#     secondary filter name               if one is found
#     {}                                  if not found
#
proc get_secondary_filter { primary_filter filt_pairs } {
  global debug

  if { $debug > 1 } {
    puts "entering get_secondary_filter"
  }

  set secondary {}
  set len [llength $filt_pairs]
  set in 0
  while { $in < $len } {
    set ff [lindex $filt_pairs $in]

    # a sanity check 
    if { [llength $ff] != 2 } {
      puts stderr "get_secondary_filter: pair $ff has length not 2 ?!"
      exit 1
    }

    set prime [lindex $ff 0]
    if { [string compare $primary_filter $prime] == 0 } {
      set secondary [lindex $ff 1]
      if { $debug > 2 } {
        puts "get_secondary_filter: pri $primary_filter sec $secondary"
      }
      break
    }
    incr in
  }

  return $secondary
}


############################################################################
# PROCEDURE: get_passband_columns
#
# DESCRIPTION: Figure out the proper columns to use in the collated 
#              output files.  That is, figure out which columns 
#              contain the primary passband data, and which the 
#              secondary passband data.
#
#              The "first_triplet_col" is the column (zero-index)
#              at which the first triplet starts; each triplet looks
#              like this:
#
#                        V   12.345  0.234
#
#              in which the first column is a passband name, the second
#              a raw magnitude, and the third a raw magnitude uncertainty.
#              We assume that triplets follow each other with no intervening
#              columns.
#
#              Place the columns containing the primary passband's
#              filter name, magnitude, and magnitude uncertainties in
#              the "pri_filt_col", "pri_mag_col", "pri_magerr_col" output args.
#              Ditto the secondary passband's values, in 
#              the "sec_filt_col", "sec_mag_col", "sec_magerr_col" output args.
#
#              Perform a check to see that all the files have similar formats.
#              If they don't, return with error code.
#
# RETURNS:
#   0                 if all goes well
#   1                 if error occurs (or if files have diff formats)
#
proc get_passband_columns { primary_filter secondary_filter collated_list \
                               first_triplet_col \
			       pri_filt_col pri_mag_col pri_magerr_col \
			       sec_filt_col sec_mag_col sec_magerr_col } {
  global debug
  upvar $pri_filt_col p_filt_col 
  upvar $pri_mag_col p_mag_col 
  upvar $pri_magerr_col p_magerr_col
  upvar $sec_filt_col s_filt_col 
  upvar $sec_mag_col s_mag_col 
  upvar $sec_magerr_col s_magerr_col

  if { $debug > 1 } {
    puts "entering get_passband_columns"
  }

  # set all values to -1 as a marker that we don't know them yet
  set p_filt_col   -1
  set p_mag_col    -1
  set p_magerr_col -1
  set s_filt_col   -1
  set s_mag_col    -1
  set s_magerr_col -1
  # and set these to 0 -- again, we don't know them yet
  set found_primary 0
  set found_secondary 0


  # we pick the first file name in the list as our test case, and examine
  #   it to find the primary and secondary filter information
  if { [llength $collated_list] < 1 } {
    puts stderr "get_passband_columns: no collated output files?"
    return 0
  }
  set file [lindex $collated_list 0]

  if { [catch { set fid [open $file "r"] } ] != 0 } {
    puts stderr "get_passband_columns: can't open file $file"
    return 1
  }
  while { [gets $fid line] != -1 } {

    # we find the first line which doesn't start with the comment character
    if { [regexp "^#" $line] == 1 } {
      continue
    }

    # we demand that the line contain at least two triplets of magnitude info
    set len [llength $line]
    set min_len [expr $first_triplet_col+5]
    if { $len < $min_len } {
      puts stderr "get_passband_columns: file $file has bad line"
      puts stderr "len $len min_len $min_len for the following line:"
      puts stderr "$line"
      return 1
    }

    # okay, now search for the primary triplet
    set found_primary 0
    set start_col $first_triplet_col
    while { $found_primary == 0 && $start_col < $len } {
      set filt [lindex $line $start_col]
      set mag [lindex $line [expr $start_col+1]]
      set magerr [lindex $line [expr $start_col+2]]

      # the first element must be string matching primary filter name
      if { [string compare $filt $primary_filter] == 0 } {
        set found_primary 1

        # the second and third elements must be floating point values
        if { [scan $mag "%lf" dummy] != 1 } {
          puts stderr "get_passband_columns: file $file has bad mag column"
    	  puts stderr "in col [expr $start_col+1] of following line"
    	  puts stderr "$line"
          return 1
        }
        if { [scan $magerr "%lf" dummy] != 1 } {
          puts stderr "get_passband_columns: file $file has bad magerr column"
	  puts stderr "in col [expr $start_col+2] of following line"
	  puts stderr "$line"
          return 1
        }
      }

      if { $found_primary == 1 } {
        set p_filt_col $start_col
        set p_mag_col [expr $start_col+1]
        set p_magerr_col [expr $start_col+2]
      }
      
      set start_col [expr $start_col+3]
    }

    if { $found_primary == 0 } {
      puts stderr "get_passband_columns: can't find primary $primary_filter"
      puts stderr "in file $file"
      return 1
    }

    # now search for the SECONDARY triplet
    set found_secondary 0
    set start_col $first_triplet_col
    while { $found_secondary == 0 && $start_col < $len } {
      set filt [lindex $line $start_col]
      set mag [lindex $line [expr $start_col+1]]
      set magerr [lindex $line [expr $start_col+2]]

      # the first element must be string matching secondary filter name
      if { [string compare $filt $secondary_filter] == 0 } {
        set found_secondary 1

        # the second and third elements must be floating point values
        if { [scan $mag "%lf" dummy] != 1 } {
          puts stderr "get_passband_columns: file $file has bad mag column"
    	  puts stderr "in col [expr $start_col+1] of following line"
    	  puts stderr "$line"
          return 1
        }
        if { [scan $magerr "%lf" dummy] != 1 } {
          puts stderr "get_passband_columns: file $file has bad magerr column"
	  puts stderr "in col [expr $start_col+2] of following line"
	  puts stderr "$line"
          return 1
        }
      }

      if { $found_secondary == 1 } {
        set s_filt_col $start_col
        set s_mag_col [expr $start_col+1]
        set s_magerr_col [expr $start_col+2]
      }
      
      set start_col [expr $start_col+3]
    }

    if { $found_secondary == 0 } {
      puts stderr "get_passband_columns: can't find secondary $secondary_filter"
      puts stderr "in file $file"
      return 1
    }

    # we've seen enough -- stop reading data from the file
    break
  }
  close $fid

  # sanity check
  if { ($found_secondary == 0) || ($found_primary == 0) } {
    puts stderr "get_passband_columns: couldn't set filter columns"
    return 1
  }


  # should check other files here ....


  return 0
}



#############################################################################
# PROCEDURE: create_output_stem
#
# DESCRIPTION: create the stem of the output file names for the
#              photometric solution/calibration program.
#
#              What we want to do is use the first collated data file
#              as the basis for the name.  It will look something
#              like this:
#
# ------------------  new convention, Disk Set 17 and later ------------
#                   /data/disk15/processed/Mhra1992373.clt
#
#              We want to strip off the directory information and the
#              final extension ".clt", to leave a stem like this:
#
#                   Mhra1992373
#
# ------------------  old convention, Disk Set 16 and earlier ------------
#                   /data/disk15/processed/M1659.826
#
#              We want to strip off the directory information
#
#                   M1659.826
# ------------------------------------------------------------------------
#
#              and change the period to an underscore.
#              Place this stem into the final argument.
#
# RETURNS
#     0                 if all goes well
#     1                 if an error occurs
#
proc create_output_stem { output_dir collated_list stem } {
  global debug
  upvar $stem output_stem

  if { $debug > 1 } {
    puts "entering create_output_stem"
  }

  # pick the first file in the collated list as the starting point
  if { [llength $collated_list] < 1 } {
    puts stderr "create_output_stem: no files in collated list?"
    return 1
  }
  set basis [lindex $collated_list 0]

  # remove the directory stuff
  set lbasis [split $basis /]
  set len [llength $lbasis]
  if { $len < 1 } {
    puts stderr "create_output_stem: empty basis name ..$lbasis.. ?!"
    return 1
  }

  set basis [lindex $lbasis [expr $len-1]]

  # now get rid of the final extension ".clt"
  if { [string match "*.clt" $basis] != 1 } {
    puts stderr "create_output_stem: can't find extension .clt in $basis?"
    return 1
  }
  set len [string length $basis]
  set stripped_basis [string range $basis 0 [expr $len-5]]

  if { $debug > 2 } {
    puts "create_output_stem: stripped_basis is $stripped_basis"
  }

  set output_stem $stripped_basis


 
  return 0
}



#############################################################################
# PROCEDURE: run_photom
#
# DESCRIPTION: Call the external program which performs a photometric
#              solution for the night and calibrates the collated
#              raw measurements.
#
#              We send any output of the external program into a special
#              "debug_file" in the output directory.  There should be
#              no output (i.e. no messages written to stdout or stderr)
#              if the external program runs properly.  However, during
#              development, the external program could generate a great
#              deal of diagnostic information -- enough to hang the TCL
#              shell.  So, we direct any output to that special file.
#
#              The results are placed in a set of files; the output file
#              names start with the stem "output_stem", and have
#              extensions as follows:
#
#              There will be _one_ output file with each of the following
#              extensions, combining information from all passbands:
#
#                       .coeff      coefficients for the photometric solution
#
#                       .cal        calibrated magnitudes in the primary 
#                                             filter
#
#              There will be _several_ output files with the following
#              extension, one per passband in which we make a solution.
#
#                     _V.comp       for all stars which appear in both the
#                     _I.comp                 reference catalog and the 
#                                             observations, a comparison 
#                                             of magnitudes in reference 
#                                             catalog and in calibrated output
#
#                                   Each file name has a suffix of 
#                                   underscore plus the passband name,
#                                   then the ".comp" extension is added.
#
#
# RETURNS
#     0                 if all goes well
#     1                 if an error occurs
#
proc run_photom { output_dir refcat_name ref_ra_col ref_dec_col \
                        ref_pri_col ref_sec_col ref_matchrad \
		        collated_list \
			col_ra_col col_dec_col col_jd_col \
			col_air_col col_quality_col \
			pri_filt_col pri_mag_col pri_magerr_col \
			sec_filt_col sec_mag_col sec_magerr_col \
			primary_filter secondary_filter \
         fixk photom_orphans \
			photom_exe output_stem debug_file } {
  global debug

  if { $debug > 1 } {
    puts "entering run_photom"
  }

  # the 'photom' program allows a more general approach to the 
  #   passbands in both the reference catalog and in the detected files.
  #   At the moment (12/10/2000), this TCL procedure is set up to
  #   deal only with two passbands, a primary and secondary.
  set ref_nfilt 2
  set det_nfilt 2

  # we need to separate the first file in the collated list from 
  #   all the rest (if they exist), due to the arrangement of arguments
  #   expected by the photometry program
  set first_collated [lindex $collated_list 0]
  set other_collated [lreplace $collated_list 0 0]
  if { $debug > 3 } {
    puts "run_photom: first_collated is ..$first_collated.."
    puts "run_photom: other_collated is ..$other_collated.."
  }

  # build the command (it's a long one)
  set cmd [format "%s %s/%s %d %d %d " \
           $photom_exe $output_dir $refcat_name $ref_ra_col $ref_dec_col \
           $ref_nfilt ]
  set cmd [format "%s %s=%d %s=%d " $cmd $primary_filter $ref_pri_col \
                 $secondary_filter $ref_sec_col]
  set cmd [format "%s %s %d %d %d %d %d " $cmd $first_collated \
                 $col_ra_col $col_dec_col $col_jd_col $col_air_col \
		 $col_quality_col ]
  set cmd [format "%s %d %d,%d,%d %d,%d,%d " $cmd $det_nfilt \
                 $pri_filt_col $pri_mag_col $pri_magerr_col \
                 $sec_filt_col $sec_mag_col $sec_magerr_col ]
  set cmd [format "%s %s radius=%s outfile=%s/%s " $cmd \
                 $other_collated $ref_matchrad $output_dir $output_stem ]
  set cmd [format "%s mode=noextinct " $cmd ]
  # we have to decode the "fixk" parameter, which looks like this:
  #       { V 0.20 } { I 0.08 } 
  #   There should be a series of pairs: filter-value, filter-value.
  #   For each pair, we create a command-line arg which combines the
  #   filter name and coeff value.  The example above would turn into
  #       fixk=V,0.20  fixk=I,0.08
  #
  set fixk_len [llength $fixk]
  foreach fixk_pair $fixk {
    if { [llength $fixk_pair] != 2 } {
      puts "run_photom: invalid fixk value $fixk_pair -- quitting"
      return 1
    }
    set fixk_filter [lindex $fixk_pair 0]
    set fixk_extinct [lindex $fixk_pair 1]
    set cmd [format "%s fixk=%s,%s" $cmd $fixk_filter $fixk_extinct]
  }
  # now add the "orphans=" option.  
  set cmd [format "%s orphans=%s " $cmd $photom_orphans]
 
  set cmd [format "%s >& %s " $cmd $debug_file ]


  if { $debug > 1 } {
    puts "run_photom: cmd is $cmd"
    set fid [open "photom.cmd" "w"]
    puts $fid $cmd
    close $fid
  }

  # run the command 
  if { [catch { eval exec $cmd  }] != 0 } {
    puts stderr "run_photom: error evaluating $cmd"
    return 1
  }

  return 0
}


##############################################################################
# PROCEDURE: save_coeffs
# 
# DESCRIPTION: This routine is called after the "photom" program has
#              been used to find the photometric solution for a night.
#              One of the outputs of the "photom" program is a file
#              with a name like
#
#                           Mhra2604977.coeff
#
#              which contains one line of information for each of the
#              images used in the solution.  Lines like this:
#
#  V=V,(V-I)  N   9403  a  0  -8.980  0.015  b  -0.025  0.005   RMS  0.058 
#  V=V,(V-I)  N   9403  a  1  -9.052  0.005  b  -0.025  0.005   RMS  0.058 
#  V=V,(V-I)  N   9403  a  2  -9.047  0.005  b  -0.025  0.005   RMS  0.058 
#
#              The sixth column (-8.980) is the zeropoint for the frame.
#              The ninth column (-0.025) is the color term for the frame,
#              which will be the same for all images in one passband
#              for the entire solution (i.e. for the entire night).
#              What we want to do is pick out the zeropoint and color term
#              from each
#              line of the .coeff file and match them with their corresponding
#              image name.  Unfortunately, the image names are not printed
#              in the .coeff file, only the image index numbers, in the fifth
#              column.  The first image pair is number 0, the second is
#              number 1, and so on.
#
#              We can do this matching of index to name because the third
#              arg to this function is a list of .clt file names in indexed
#              order.  We can use them to figure out the image names.
#
#              After we have the name for each line in the .coeff file,
#              we save the zeropoint and color term for the image in 
#              the "make_list.out" file, for future reference.
#
#  RETURNS:
#    0                if all goes well
#    1                if an error occurs
#
proc save_coeffs { output_dir output_stem collated_list } {
  global debug

  if { $debug > 2 } {
    puts "save_coeffs: collated_list is $collated_list"
  }


  # figure out the name of the .coeffs file, and open it for reading
  set coeffs_file [format "%s/%s.coeff" $output_dir $output_stem]
  if { [catch { set fid [open $coeffs_file "r"] } ] != 0 } {
    puts stderr "save_coeffs: can't open file $coeffs_file"
    return 1
  }

  # now go through the coeffs file one line at a time
  #   figure out the image name associated with each line
  #   pick out the zeropoint and colorterm for each image
  #   and save them in the "make_list.out" file
  set index_pos 0
  while { [gets $fid line] != -1 } {

    # ignore lines with comment characters
    if { [regexp "^#" $line] == 1 } {
      continue
    }

    # each line should look like this:
    #  V=V,(V-I)  N   9403  a  8  -8.935  0.006  b  -0.025  0.005   RMS  0.058 
    # with 12 words
    set num_words 12
    set len [llength $line]
    if { $len != $num_words } {
      puts stderr "save_coeffs: file $coeffs_file has bad line:"
      puts stderr "..$line.."
      return 1
    }

    # okay, now get four pieces of information numbers from this line:
    #    the filter
    #    the image index
    #    the zeropoint
    #    the color term
    set filt [lindex $line 0]
    set filt [lindex [split $filt =] 0]
    set image_index [lindex $line 4]
    set zeropoint [lindex $line 5]
    set colorterm [lindex $line 8]
    if { $debug > 2 } {
      puts "save_coeffs:  filt $filt  index $image_index  zp $zeropoint  ct $colorterm"
    }

    # figure out the name of the .clt file which corresponds to this
    #   entry in the .coeff file.  
    set clt_name [lindex $collated_list $image_index]
    if { $debug > 2 } {
      puts "save_coeffs: full .clt name is $clt_name"
    }
    # get rid of the leading directory portions of the name, 
    #   leaving just the file name
    set clt_name_pieces [split $clt_name / ]
    set clt_name [lindex $clt_name_pieces [expr [llength $clt_name_pieces]-1]]
    if { $debug > 2 } {
      puts "save_coeffs: tail .clt name is $clt_name"
    }

    # pick out the portion of the .clt file name which contains an 
    #   encoded Julian Date for the file
    #   BEWARE: this isn't very robust!  If we change the format
    #   of the .clt files, this won't work any more.
    #   MWR 4/11/2003
    set clt_jd [string range $clt_name 4 10]

    # now we need to pick the name of the .clt file which corresponds
    #   to this entry in the .coeffs file
    # can use "select_input_list" to get all V image names, which look like
    #
    #             hvra2604806.fits
    #
    # and the .clt files have names like this:
    #
    #             Mhra2604800.clt
    # 
    # so we can use the JD portion of the names to find a match
    set klist [list [list "filter" $filt] ]
    set possible_names [select_input_list $klist]
    set found 0
    foreach name $possible_names {
      if { [string match *$clt_jd* $name] == 1 } {
        # okay, we found the match!
        #   Now we can save the zeropoint and colorterm for this image
        #   in the "make_list.out" file 
        set found 1
        if { $debug > 2 } {
          puts "save_coeffs: match found $clt_name $name"
        }
        set klist [list "zeropoint" $zeropoint]        
        if { [replace_image_value $name $klist] != 0 } {
          puts stderr "save_coeffs: replace_image_value fails for zeropoint $clt_name"
          return 1
        }
        set klist [list "colorterm" $colorterm]        
        if { [replace_image_value $name $klist] != 0 } {
          puts stderr "save_coeffs: replace_image_value fails for colorterm $clt_name"
          return 1
        }

        break
      }
    }
    if { $found == 0 } {
      puts stderr "save_coeffs: couldn't find match for $clt_name "
      return 1
    }

  }
  close $fid
  
  return 0

}


#############################################################################
# PROCEDURE: copy_list_file
#
# DESCRIPTION: Make a copy of the "make_list.out" file, giving the copy
#              a name with the same stem as the .cal file, but extension
#              .list.
#
# RETURNS:
#    0             if all goes well
#    1             if an error occurs
#
proc copy_list_file { output_dir output_stem } {
  global debug

  if { $debug > 2 } {
    puts "entering copy_list_file "
  }

  # get the name of the existing list file
  set list_file [get_list_name]
  if { [file exists $list_file] != 1 } {
     puts stderr "copy_list_file: can't find file $list_file"
     return 1
  }
  
  # build the name of our copy
  set new_file [format "%s/%s.list" $output_dir $output_stem]

  if { $debug > 0 } {
    puts "copy_list_file: about to copy $list_file to $new_file"
  }
  
  # now, make the copy
  exec cp $list_file $new_file

  # all done
  return 0

}




############################################################################
# Here, we start the namespace "Photom", which we use to store
#   information about the "archivable" output file stem.  That is,
#   the name of the stem of the major output files one might
#   archive:
#              stem.cal        output astrometry and photometry for all star
#              stem.list       properties of each image
#              stem.param      parameters used to reduce data
#   
namespace eval Photom {
  namespace export init_photom_stem get_photom_stem
  variable Photom_Stem {}


  ##########################################################################
  # Set the variable "Photom_Stem" in the "Photom" namespace 
  #
  # RETURNS:
  #     0                if all goes well
  #     1                otherwise
  #
proc init_photom_stem { stem } {
  global debug
  variable Photom_Stem

  if { $debug > 0 } {
    puts "entering init_photom_stem"
  }

  set Photom_Stem $stem

  return 0
}



  ############################################################################
  # Return the value of the "Photom_Stem" private variable
  #
  # usage:   get_photom_stem     
  # 
  # Returns:
  #    value of the Photom_Stem          
  #
proc get_photom_stem { } {
   global debug
   variable Photom_Stem

   if { $debug > 1 } {
     puts "entering get_photom_stem"
   }

   return $Photom_Stem
}

}
# end of namespace for Photom


