#!/usr/bin/perl -w
#
# pacmake.pl
# Created:     Thu Jan  3 10:50:33 2008 by Koehler@Six
# Last change: Thu Mar 17 11:46:02 2011
#
# This file is Hellware!
# It may send you and your data straight to hell without further notice.
#
# CRAP: environment should be run after all the LEVEL1 files have been created
#
print "pacmake Version 0.9\n\n";

$debug = 0;

@t = localtime(time);
#$esorex= ($t[2] < 1) ? "valgrind esorex" : "esorex";
$esorex= ($t[6] > 5) ? "valgrind esorex" : "esorex";	# grind on Saturday
#$esorex= "valgrind esorex";

#######################################################

sub get_keywords {
    my($f) = @_;

    printf "%-45s",$f;

    if (exists $MJD_obs{$f} and $MJD_obs{$f} != 0.) {
	print "already slewed\n";
	return 0;	# it's allright...
    }
    if (not open(IN, ($f =~ /\.gz$/) ? "gzcat $f |" : $f)) {
	print "Can't open $f!\n";
	return 1;	# this is bad!
    }
    $MJD_obs{$f}  = 0.;
    $template{$f} = '';
    $tplstart{$f} = '';
    $obsstart{$f} = '';
    $ins_mood{$f} = '';
    $dprgronk{$f} = '';
    $pro_catg{$f} = '';
    $target1{$f}  = '';
    $target2{$f}  = '';
    $dpr_catg = $dpr_tech = $dpr_type = '';

    if (not read(IN,$_,80) or $_ !~ /SIMPLE  = /) {
	print " - not a FITS file\n";
    } else {
      while( read(IN,$_,80)) {
	($val) = m,=\s+["']?([^'"]*[^'" ])\s*['"]?\s*/,;

	if (/MJD-OBS/ and $MJD_obs{$f} == 0.) {
	    ($mjd) = m,=\s+["']?\s*([0-9.]+)\s*['"]?,;
	    $MJD_obs{$f} = $mjd;
	    printf "%10.4f ", $mjd;
	}
	elsif (/HIERARCH ESO QC MJD START/) {
	    ($mjd) = m,=\s+["']?\s*([0-9.]+)\s*['"]?,;
	    $MJD_obs{$f} = $mjd;
	    printf "\tSt%10.4f ", $mjd;
	}
	elsif (/HIERARCH ESO TPL ID/) {
	    $tpl = $val;
	    $template{$f} = lc($tpl);
	    printf "%-28.28s ", "'$tpl'";
	}
	elsif (/HIERARCH ESO TPL NAME/ and $template{$f} eq '') {
	    # just in case TPL ID is missing (e.g. in real environment data)
	    $template{$f} = lc($val);
	    printf "%-28.28s ", "'$tpl'";
	}
	elsif (/HIERARCH ESO TPL START/) {
	    ($tst) = m,=\s+["']?([^'\"]+)\s*['"]?\s*/,;
	    $tplstart{$f} = uc($tst);	# should be ..T...
	    #printf "%-5.19s ", $tst;
	}
	elsif (/HIERARCH ESO OBS START/) {
	    ($ost) = m,=\s+["']?([^'\"]+)\s*['"]?\s*/,;
	    $obsstart{$f} = uc($ost);	# should be MJD or ..T..
	    #printf "%-5.19s ", $tst;
	}
	elsif (/HIERARCH ESO INS MODE/) {
	    ($im) = $val;
	    $ins_mood{$f} = uc($im);
	    print "'$im'";
	}
	elsif (/HIERARCH ESO DPR CATG/) {
	    $dpr_catg = $val;
	}
	elsif (/HIERARCH ESO DPR TECH/) {
	    $dpr_tech = $val;
	}
	elsif (/HIERARCH ESO DPR TYPE/) {
	    $dpr_type = $val;
	}
	elsif (/HIERARCH ESO PRO CATG/) {
	    ($ctg) = m,=\s+["']?([^"']*[^'" ])\s*['"]?\s*/,;
	    $pro_catg{$f} = uc($ctg);
	    print "'$ctg'";
	}
	elsif (/HIERARCH ESO OCS TARG([12]) ID/) {
	    $tn = $1;
	    ($trg) = m,=\s+["']?([^"']*[^'" ])\s*['"]?\s*/,;
	    ($tn eq 1)? $target1{$f} : $target2{$f} = uc($trg);
	    print "$tn='$trg'";
	}
	elsif (/^END     /) { last; }
      }
    }
    close IN;
    $dprgronk{$f} = "$dpr_catg:$dpr_tech:$dpr_type";

    print "$dprgronk{$f}.\n";
    return 0;	# alles prima
}

#############################################################################

sub find_same_tplstart {
    my($file) = @_;

    @files = ();
    for (@filelist) {
	# find same category, same template, not reduced,
	# but don't mix NORMAL and SWAP

	#print "same tpl? $_\n";
	if ($pro_catg{$_} eq '' and
	    $dprgronk{$_} eq $dprgronk{$file} and
	    $ins_mood{$_} eq $ins_mood{$file} and
	    $tplstart{$_} eq $tplstart{$file} and
	    abs($MJD_obs{$_} - $MJD_obs{$file}) lt 1.0/24.) {
	    # OBs should be shorter than one hour
	    push @files, $_;
	}
    }
    return sort(@files);
}

#############################################################################

sub find_calib_file {
    my($categ,$MJD,$silent) = @_;

    print "find_calib: filelist at start is:\n",join("\n",@filelist),"\n" if ($debug > 1);

    $calfile = '';
    for $cf (@filelist) {
	#print "  $categ: $cf\n" if ($categ eq 'VLTIRESP');
	if (uc($pro_catg{$cf}) eq $categ and $MJD_obs{$cf} < $MJD) {
	    # make sure we use the last calfile before $MJD
	    if ($calfile eq '' or $MJD_obs{$calfile} < $MJD_obs{$cf}) {
		$calfile = $cf;
	    }
	}
    }
    print "calfile = /$calfile/\n" if $debug;
    if ($calfile eq '' and !$silent) { print "  No usable $categ found!\a\n"; }
    return $calfile;
}

#############################################################################

sub find_spectrum {
    my($target) = @_;

    print "spectrum for $target?\n";

    return '' if ($target eq 'UNKNOWN');	# simulator code for "NONE"

    # the interesting target in STARSPECS is always OCS TARG2

    $calfile = '';
    for $cf (@filelist) {
	if (uc($pro_catg{$cf}) eq 'STARSPEC' and $target2{$cf} eq $target) {
	    #print "  $categ: $cf\n";
	    # make sure we use the last calfile before $MJD
	    if ($calfile eq '' or $MJD_obs{$calfile} < $MJD_obs{$cf}) {
		$calfile = $cf;
	    }
	}
    }
    print "calfile = /$calfile/\n" if $debug;
    if ($calfile eq '') { print "  No usable starspectrum for $target found!\a\n"; }
    #else { print "spectstarum for $target is $calfile\n"; }
    return $calfile;
}


#############################################################################

sub fix_ins_mode {
    my($old,$mode) = @_;

    ($new = $old) =~ s/.fits/fx.fits/;
    print " fix_ins_mode: $old($ins_mood{$old}) -> $new($mode)\n";
    if (not -f $new or (-M $old < -M $new)) {
	# new does not exist or is older than old
	system("cp $old $new; chmod u+w $new; fkedit -m 'HIERARCH ESO INS MODE' '$mode' $new");
    }
    return $new;
}

#############################################################################

sub esorex {
  my($rcp,$f,$res,@frames) = @_;

  ($sof = $f) =~ s/(\.fits)?$/.sof/;
  ($out = $f) =~ s/(\.fits)?$/.out/;
  print ERX "esorex --suppress-prefix pacma_$rcp $sof\n";

  print " -> $res ";
  if (not -f $res or (-M $f < -M $res)) {
      # res does not exist or is older than f
      unlink $res;	# make sure it does not exist
      print "does not exist, call esorex!\n";

      open SOF, "> $sof" or die "Can't create sof for pacma_$rcp: $!\a\n";
      for (@frames) {
	  print   "\t$_\n";
	  print SOF "$_\n";
      }
      close SOF;

      print ("$esorex --suppress-prefix pacma_$rcp $sof > $out 2>&1\n");
      system("$esorex --suppress-prefix pacma_$rcp $sof > $out 2>&1");
      $status = $?;
      if (open OUT, "$out") {
	  while(<OUT>) { print "\t$_" if /\[ ERROR \]/; }
	  close OUT;
      }
      print "Return status: $status\n";
      if ($status) {
	open CL, "> crash.log" or die "Can't write crash.log: $!\a\n";
	print CL "esorex --suppress-prefix pacma_$rcp $sof returned status $status\n";
	close CL
      }
  } else {
      print "exists\n";
  }
}


#############################################################################

print "scanning files...\n";

@arglist = sort @ARGV;

#push @arglist, glob('/home/istilz/test/coco_cat/*.fits');

@filelist= ();

print "Getting header keywords...\n";
while ($f = shift @arglist) {
    if (get_keywords($f) == 0) { push @filelist, $f; }
}

open ERX, ">> esorex.sh" or die "Can't write esorex.sh: $!\a\n";

rename "crash.log", "crash.log.old";

#############################################################################

print "\n=============================================================================\n";
print "online processing...\n\n";

for $f (@filelist) {
    if ($pro_catg{$f} eq '') {
	# this is raw data
	print "-"x72,"\n";
	if ($template{$f} =~ /cal_lab_dark$/i) {
	    print " $f (LAB_DARK_RAW)\n";
	    #@labdarks = ();
	    #for $l (@filelist) {
	    #	if ($template{$l} eq $template{$f} and
	    #	    $tplstart{$l} eq $tplstart{$f} and $pro_catg{$l} eq '') {
	    #	    push @labdarks, $l;
	    #	}
	    #}
	    #@labdarks = sort @labdarks;
	    @labdarks = find_same_tplstart($f);

	    ($res = $first = $labdarks[0]) =~ s/(\.fits)?$/_LABDARK.fits/;
	    if ($f ne $first) {
	      print "	- not the first file from template\n";
	    } else {
	      @frames = ();
	      for (@labdarks) { push @frames, "$_	LAB_DARK_RAW"; }
	      esorex("labdark",$first,$res,@frames);
	      # the output filename is based on the input file with shortest DIT
	      # we don't know which one this is, so let's check all :-)
	      $rcnt=0;
	      foreach ( @labdarks ) {
		  ($res = $_) =~ s/(\.fits)?$/_LABDARK.fits/;
		  if(-e $res and !exists($MJD_obs{$res})) {
		      push @filelist,$res;
		      $rcnt++;
		      get_keywords($res);
		  }
	      }
	      print " $rcnt LABDARK(s) created\n";
	    }
	}
	elsif ($template{$f} =~ /cal_lab_flat$/i) {
	    print " $f (LAB_FLAT_RAW)\n";
	    @labflats = ();
	    for $l (@filelist) {
		if ($template{$l} eq $template{$f} and
		    $tplstart{$l} eq $tplstart{$f} and $pro_catg{$l} eq '') {
		    push @labflats, $l;
		}
	    }
	    @labflats = sort @labflats;
	    $res = $first = $labflats[0];
	    if ($f ne $first) {
	      print "	- not the first file from template\n";
	    } else {
		$res =~ s/(\.fits)?$/_LABFLAT.fits/;
		if (($labdark= find_calib_file('LAB_DARK',$MJD_obs{$f})) eq '') { next; }
		@frames = ();
		for (@labflats) { push @frames, "$_	LAB_FLAT_RAW"; }
		push @frames, "$labdark	LAB_DARK";
		esorex("labflat",$first,$res,@frames);
		if(-e $res and !exists($MJD_obs{$res})) { push @filelist,$res;	get_keywords($res); }
	    }
	}
	elsif ($template{$f} =~ /cal_sky_(dark|back)/i or $dprgronk{$f} eq 'CALIB:IMAGE:SKY') {
	    print " $f (SKY_BARK_RAW)\n";

	    @darks = find_same_tplstart($f);

	    print "skybacks:",@darks,"\n";

	    #($res = $first = $darks[0]) =~ s/(\.fits)?$/_SKYBACK.fits/;
	    #if ($f ne $first) {
	    #   print "	- not the first file from template, reducing single file\n";
	    print " reducing skybacks in single file mode\n";
	    $ff = $f;	# don't mess with @filelist
	    if ($ins_mood{$f} eq "SWAP") { $ff = fix_ins_mode($ff,'NORMAL  '); }
	    ($res = $ff) =~ s/(\.fits)?$/_SKYBACK.fits/;
	    esorex("skybackground",$ff,$res,"$ff	SKY_BACK_RAW");
	    #} else {
	    # @frames = ();
	    # for (@darks) { push @frames, "$_	SKY_BACK_RAW"; }
	    # esorex("skybackground",$first,$res,@frames);
	    #}
	    if(-e $res and !exists($MJD_obs{$res})) { push @filelist,$res;	get_keywords($res); }
	}
	elsif ($template{$f} =~ /sky_flat/i or $dprgronk{$f} eq 'CALIB:IMAGE:FLAT,SKY') {
	    print " $f (SKY_FLAT_RAW)\n";

	    @skyflats= find_same_tplstart($f);

	    if ($f ne $skyflats[0]) {
		print "	- not the first file from template\n";
	    } else {
		if (($sky1 = find_calib_file('SKY_BACK',$MJD_obs{$f})) eq '') { next; }
		$sky2 = find_calib_file('SKY_BACK', $MJD_obs{$sky1},1);

		@frames= ();
		for (@skyflats) {
		    if ($ins_mood{$_} eq "SWAP") { $_ = fix_ins_mode($_,'NORMAL  '); }
		    push @frames, "$_	STAR_FLAT_RAW";
		}
		push @frames, "$sky2	SKY_BACK" if ($sky2 ne '');
		push @frames, "$sky1	SKY_BACK";

		($res = $skyflats[0]) =~ s/(\.fits)?$/_STARFLAT.fits/;

		esorex("starflat",$f,$res,@frames);
		#print "STARFLAT $skyflats[0] -> $res\n";
		if(-e $res and !exists($MJD_obs{$res})) { push @filelist,$res;	get_keywords($res); }
	    }
	}
	elsif ($dprgronk{$f} eq 'CALIB:IMAGE:COMBINED FLAT,SKY') {
	    print " $f (COMBINED FLAT - ignored)\n";
	}
	elsif ($template{$f} =~ /cal_lab_FSUresponse$/i) {
	    print " $f (LAB_FSURESP_RAW)\n";

	    ($res = $f) =~ s/(\.fits)?$/_FSURESP.fits/;
	    #if (($labdark= find_calib_file('LAB_DARK',$MJD_obs{$f})) eq '') { next; }
	    #@frames= ("$f	LAB_FSURESP_RAW",
	    #	      "$labdark	LAB_DARK");
	    @frames= ("$f	LAB_FSURESP_RAW");
	    #esorex("fsuresponse --THRESHOLD=0.5",$f,$res,@frames);
	    esorex("fsuresponse",$f,$res,@frames);
	    if(-e $res and !exists($MJD_obs{$res})) { push @filelist,$res;	get_keywords($res); }
	}
	elsif ($template{$f} =~ /_VLTIresponse$/i) {
	    print " $f (VLTIRESP_RAW)\n";

	    ($res = $f) =~ s/(\.fits)?$/_VLTIRESP.fits/;
	    #$sky = find_calib_file('SKY_BACK',$MJD_obs{$f});
	    $fsu = find_calib_file('FSURESP', $MJD_obs{$f});
	    next if ($fsu eq '');

	    @frames= ("$f	CAL_VLTIRESP_RAW",
		      "$fsu FSURESP",
		      "STARSPECTRUM.fits	STARSPEC");
	    esorex("vltiresponse",$f,$res,@frames);
	    if(-e $res and !exists($MJD_obs{$res})) { push @filelist,$res;	get_keywords($res); }
	}
	elsif ($template{$f} =~ /_obs_spectrum$/i) {
	    print " $f (OBS_SPECTRUM)\n";

	    ($res = $f) =~ s/(\.fits)?$/_STARSED.fits/;
	    #$sky = find_calib_file('SKY_BACK',$MJD_obs{$f});
	    $fsu = find_calib_file('FSURESP', $MJD_obs{$f});
	    $vlti= find_calib_file('VLTIRESP',$MJD_obs{$f});
	    next if ($fsu eq '' or $vlti eq '');

	    @frames= ("$f	OBS_SPECTRUM_RAW",
		      "$fsu FSURESP",
		      "$vlti VLTIRESP");
	    esorex("starspectrum",$f,$res,@frames);
	    if(-e $res and !exists($MJD_obs{$res})) { push @filelist,$res;	get_keywords($res); }
	} # end of starspectrum
	elsif ($template{$f} =~ /_obs_(astrometry|generic)$/i
	       or  $dprgronk{$f} eq 'SCIENCE:INTERFEROMETRY:OBJECT,ASTROMETRY') {
	    print " $f ($template{$f} => OBS_ASTROMET)\n";

	    $ff = $f;	# don't change @filelist
	    if ($ins_mood{$ff} eq "SWAP") { $ff = fix_ins_mode($ff,'SWAPPED '); }
	    ($res = $ff) =~ s/(\.fits)?$/_LEVEL1.fits/;

	    $sky1 = find_calib_file('SKY_BACK', $MJD_obs{$f});
	    next if ($sky1 eq '');

	    $flt  = find_calib_file('STAR_FLAT',$MJD_obs{$f});
	    $fsu  = find_calib_file('FSURESP',  $MJD_obs{$f});
	    next if ($flt eq '' or $fsu eq '');

	    if ($ins_mood{$f} =~ /^SINGLE/) {
		$sky2 = '';
		$fsu2 = '';
	    } else {
		$fsu2 = find_calib_file('FSURESP',  $MJD_obs{$fsu},1);
		$sky2 = find_calib_file('SKY_BACK', $MJD_obs{$sky1}); # if ($ins_mood{$sky1} =~ /^SINGLE/);
	    }
	    @frames= ( "$ff	OBS_ASTROMET_RAW" );
	    push @frames, "$sky2	SKY_BACK" if ($sky2 ne '');
	    push @frames, "$sky1	SKY_BACK";
	    push @frames, "$flt	STAR_FLAT";
	    push @frames, "$fsu	FSURESP";
	    push @frames, "$fsu2	FSURESP" if ($fsu2 ne '');
	    esorex("sciave",$f,$res,@frames);
	    if(-e $res and !exists($MJD_obs{$res})) { push @filelist,$res;	get_keywords($res); }
	}
	elsif ($template{$f} =~ /_rec_environment$/i or $dprgronk{$f} eq 'CALIB:OTHER:SENSORS') {
	    print " $f (ENVIRONMENT) - later\n";
	}
	elsif ($template{$f} =~ /pacman_obs_scanning/i) {
	    print "$f: \"$template{$f}\" - ignored\n";
	}
	else {
	    print "$f:\nI don't know what to do against template \"$template{$f}\"\n";
	    print "DPR-gronk: $dprgronk{$f}.\n";
	}

    }	# end of raw data
} # end of online crapping

#############################################################################

print "\n=============================================================================\n";
print "\noffline processing...\n\n";

for $f (@filelist) {
    print "catg($f)?\n" if $debug;
    if ($pro_catg{$f} eq '') {
	# this is raw data
	if ($template{$f} =~ /_rec_environment$/i or $dprgronk{$f} eq 'CALIB:OTHER:SENSORS') {
	    print " $f (ENVIRONMENT)\n";

	    @l1list = ();
	    for $l1 (@filelist) {
		#print "$l1? $pro_catg{$l1} $MJD_obs{$l1} $MJD_obs{$f}\n";
		if (uc($pro_catg{$l1}) eq 'LEVEL1' and
		    $MJD_obs{$l1} > $MJD_obs{$f} and $MJD_obs{$l1} <= $MJD_obs{$f}+1) {
		    ($l1e = $l1) =~ s/1.fits/1E.fits/;
		    print "$l1 -> $l1e ";
		    if (not -f $l1e or (-M $l1 < -M $l1e) or (-M $f < -M $l1e)) {
			# res does not exist or is older than f
			print "does not exist or is old\n";
			push @l1list, $l1;
		    } else { print "exists\n"; }
		}
	    }
	    if (@l1list) {
		@frames= ( "$f	LAB_ENVIREC_RAW" );
		for $l1 (@l1list) { push @frames, "$l1	LEVEL1"; }
		esorex("environment",$f,"(LEVEL1E)",@frames);
	    } else {
		print "nothing new.\n";
	    }
	    for $l1 (@l1list) {
		($l1e = $l1) =~ s/1.fits/1E.fits/;
		if(-e $l1e and !exists($MJD_obs{$l1e})) {
		    push @filelist,$l1e;  get_keywords($l1e);
		}
	    }
	}
	#else { print "$f:\nI don't know what to do against template $template{$f}\n"; }
	# should have been done in online proc.

    }	# end of raw data
    elsif ($pro_catg{$f} eq 'LAB_DARK' or
	   $pro_catg{$f} eq 'LAB_FLAT' or
	   $pro_catg{$f} eq 'SKY_BACK' or
	   $pro_catg{$f} eq 'STAR_FLAT' or
	   $pro_catg{$f} eq 'FSURESP'  or
	   $pro_catg{$f} eq 'VLTIRESP' or
	   $pro_catg{$f} eq 'STARSPEC' or
	   $pro_catg{$f} =~ /^COCO_/ ) {
	print " $f [$pro_catg{$f}] - nothing to do\n";
    }
    elsif ($pro_catg{$f} eq 'LEVEL1') {
	print " $f [LEVEL1]\n";
	print "targets: $target1{$f}, $target2{$f}\n";

	($res = $f) =~ s/(_LEVEL1\.fits)?$/_LEVEL2.fits/;
	$env  = find_calib_file('LEVEL1E', $MJD_obs{$f} + 1.0/1440.);
	$fsu  = find_calib_file('FSURESP', $MJD_obs{$f} + 12.);	# responses may be later
	if ($ins_mood{$f} !~ /^SINGLE/ and $ins_mood{$fsu} =~ /^SINGLE/) {
	    $fsu2 = find_calib_file('FSURESP',  $MJD_obs{$fsu},1);
	} else { $fsu2 = '' }

	$vlti = find_calib_file('VLTIRESP',$MJD_obs{$f} + 12.);
	$spec1= ($target1{$f} ne '') ? find_spectrum( $target1{$f}) : '';
	$spec2= ($target2{$f} ne '') ? find_spectrum( $target2{$f}) : '';
	if ($target1{$f} eq '' and $target2{$f} eq '') {
	    # dirty hack for COMM13
	    $spec1 = 'STARSPECTRUM.fits';
	    # even dirtier hack for COMM14
	    if ($ins_mood{$f} !~ /^SINGLE/) { $spec2 = $spec1 }
	}
	# no env is ok (?)
	next if ($fsu eq '') or ($vlti eq '') or (($spec1 eq '') and ($spec2 eq ''));

	$coce = find_calib_file('COCO_ENV',$MJD_obs{$f});
	if ($coce eq '') {
	    print ("no COCO_ENV found, making it myself\n");
	    print ("$esorex --suppress-prefix pacma_auxiliary --CREATE=COCO_ENV\n");
	    system("$esorex --suppress-prefix pacma_auxiliary --CREATE=COCO_ENV");
	    $coce = "COCO_ENVCAT_EMPTY.fits";
	    push @filelist,$coce;  get_keywords($coce);
	}
	#print "$f  = $MJD_obs{$f},\n$env = $MJD_obs{$env}\n";

	@frames= ("$f	LEVEL1",
		  "$coce	COCO_ENV",
		  "$vlti	VLTIRESP",
		  "$fsu	FSURESP" );
	push @frames, "$fsu2	FSURESP"    if ($fsu2 ne '');
	push @frames, "$env	LEVEL1E"    if ($env  ne '');
	push @frames, "$spec1	STARSPEC_A" if ($spec1 ne '');
	push @frames, "$spec2	STARSPEC_B" if ($spec2 ne '');
	esorex("scired1",$f,$res,@frames);
	if(-e $res and !exists($MJD_obs{$res})) { push @filelist,$res;	get_keywords($res); }
    }
    elsif ($pro_catg{$f} =~ /LEVEL1E/) {
	print " $f [$pro_catg{$f}] - no further reduction\n";
    }
    elsif ($pro_catg{$f} eq 'LEVEL2') {
	print " $f [LEVEL2]\n";

	@noswano = ();
	for $l2 (@filelist) {
	    if ($pro_catg{$l2} eq 'LEVEL2' and $obsstart{$l2} eq $obsstart{$f}) {
		push @noswano, $l2;
	    }
	}
	if (scalar(@noswano) < 3) {
	    print " only ".scalar(@noswano)." L2 files, not enough for scired2\n";
	    print join("\n",@noswano),".\n";
	} else {
	    @noswano = sort @noswano;

	    ($res = $first = $noswano[0]) =~ s/(_LEVEL2\.fits)?$/_LEVEL3.fits/;
	    $wbas = find_calib_file('COCO_WBASE',$MJD_obs{$f});
	    $ocat = find_calib_file('COCO_OBCAT',$MJD_obs{$f});
	    $cols = find_calib_file('COCO_LEAPSEC',$MJD_obs{$f});
	    $coje = find_calib_file('COCO_JPLEPH',$MJD_obs{$f});
	    next if ($wbas eq '' or $ocat eq '' or $cols eq '' or $coje eq '');

	    @frames= ();
	    for (@noswano) {
		system("fkedit -m 'HIERARCH ESO QC VALID4' 'FSUA,FSUB' $_");	# make it go!
		push @frames, "$_	LEVEL2";
	    }
	    push @frames, "$wbas	COCO_WBASE";
	    push @frames, "$ocat	COCO_OBCAT";
	    push @frames, "$cols	COCO_LEAPSEC";
	    push @frames, "$coje	COCO_JPLEPH";
	    #esorex("scired2 --WEIGHT=false",$first,$res,@frames);
	    esorex("scired2",$first,$res,@frames);
	    if(-e $res and !exists($MJD_obs{$res})) { push @filelist,$res;  get_keywords($res); }
	}
    }
    elsif ($pro_catg{$f} =~ /LEVEL3/) {
	print " $f [$pro_catg{$f}] - end of piepline\n";
    }
    else { print "unknown category $pro_catg{$f}\n"; }

}

#############################################################################
#
# Baseline works on LEVEL2, but wait till we have all of them
#
@frames= ("BASELINE_CALIBRATOR_CATALOG.fits COCO_BLCAT",
	  "OBERVER_CATALOG.fits             COCO_OBCAT" );

if (not -f 'BASELINE_CALIBRATOR_CATALOG.fits') {
    print "\nno Baseline-catalog, cannot run baseline recipe\n";
} else {
    $res = 'WBASE.fits';	# result of baseline
    $run = 0;
    for $f (@filelist) {
	if ($pro_catg{$f} eq 'LEVEL2') {
	    push @frames, "$f	LEVEL2";

	    $run= 1 if (not -f $res or (-M $f < -M $res));	# res does not exist or is older than f
	}
    }
    if ($run) {
	esorex("baseline","Baseline",'WBASE.fits',@frames);
    } else {
	print "No new LEVEL2-data for baseline found\n";
    }
}

#############################################################################
#
# scired3 - collect LEVEL3, and start all over again
#
@frames= ();
$first = "";

for $f (@filelist) {
    if ($pro_catg{$f} eq 'LEVEL3') {
	$first= $f unless $first;
	push @frames, "$f	LEVEL3" if ($target1{$f} eq $target1{$first});
    }
}

if (@frames > 2) {
    $ocat = find_calib_file('COCO_OBCAT',  $MJD_obs{$first});
    $coje = find_calib_file('COCO_JPLEPH', $MJD_obs{$first});
    if ($ocat ne '' and $coje ne '') {
	push @frames, "$ocat	COCO_OBCAT";
	push @frames, "$coje	COCO_JPLEPH";
	esorex("scired3 --WEIGHT=false",$first,'PACMA_COCO_DIFFCAT.fits',@frames);
    }
} else {
    print "Not enough LEVEL3-data for scired3++ found\n";
}

#############################################################################

close ERX;

print "pacmake finished. Good bye.\n";
print "=============================================================================\n";
