/*===========================================================================
  Copyright (C) 2001 European Southern Observatory (ESO)
 
  This program is free software; you can redistribute it and/or 
  modify it under the terms of the GNU General Public License as 
  published by the Free Software Foundation; either version 2 of 
  the License, or (at your option) any later version.
 
  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.
 
  You should have received a copy of the GNU General Public 
  License along with this program; if not, write to the Free 
  Software Foundation, Inc., 675 Massachusetss Ave, Cambridge, 
  MA 02139, USA.
 
  Corresponding concerning ESO-MIDAS should be addressed as follows:
    Internet e-mail: midas@eso.org
    Postal address: European Southern Observatory
            Data Management Division 
            Karl-Schwarzschild-Strasse 2
            D 85748 Garching bei Muenchen 
            GERMANY
===========================================================================*/

#ifdef HAVE_CONFIG_H
#  include <config.h>
#endif

/* C functions include files */ 
#include <ctype.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/* MIDAS include files */
#include <flames_stripfitsext.h>
#include <flames_midas_def.h>
/* FLAMES-UVES include files */ 
#include <flames_merge.h>
#include <flames_uves.h>
#include <uves_msg.h>
#include <flames_newmatrix.h>

int flames_merge(const char *INTER_IMA,
                 const char *INTER_SIGMA,
                 const char *INTER_MASK,
                 const char *MBASENAME,
                 const double *MASKTHRES,
                 const double delta1,
                 const double delta2)
{ 
  int i=0;
  int j=0;
  int joffset=0;
  int nval=0;
  char infile[81];
  char insigma[81];
  char inmask[81];
  char basename[81];
  char mbasename[81];
  int infileid=0;
  int insigmaid=0;
  int inmaskid=0;
  int naxis=0;
  int unit=0;
  int null=0;
  double start[2]={0,0};
  double step[2]={0,0};
  int npix[2]={0,0};
  double start2[2]={0,0};
  double step2[2]={0,0};
  int npix2[2]={0,0};
  double *wstart=0;
  int *nptot=0;
  double *wstart2=0;
  int *nptot2=0;
  frame_data **spectrum=0;
  frame_data **sigma=0;
  float **mask=0;
  frame_data *vecspectrum=0;
  frame_data *vecsigma=0;
  float *vecmask=0;
  double mstart=0;
  double mstep=0;
  int ijindex=0;
  int shiftedj=0;
  int mnpix=0;
  double maskthres=0;
  frame_data weight=0;
  frame_data *mspectrum=0;
  frame_data *msigma=0;
  frame_mask *mmask=0;
  char mspecname[85];
  char msigmaname[85];
  char mmaskname[85];
  int mspecid=0;
  int msigmaid=0;
  int mmaskid=0;
  int mnaxis=1;
  frame_data minimum=0;
  frame_data maximum=0;
  char ident[73];
  char cunit[2][16];
  float cuts[4]={0,0,0,0};
  memset(ident, 0, 73);
  memset(cunit[0], 0, 32);
  strncpy(cunit[0], "Relative flux   ", 16);
  strncpy(cunit[1], "Wavelength      ", 16);



  SCSPRO("flames_merge"); /* Get into MIDAS Env. */

  /*
  // read the file names from the MIDAS environment 
  uves_msg_warning("ok1 inter_ima=%s",INTER_IMA);
  if (SCKGETC(INTER_IMA, 1, 60, &nval, infile) != 0) {
    SCTPUT("Error reading the rebinned spectrum name");
    return flames_midas_fail();
  }

  if (SCKGETC(INTER_SIGMA, 1, 60, &nval, insigma) != 0) {
    SCTPUT("Error reading the rebinned variances name");
    return flames_midas_fail();
  }

  if (SCKGETC(INTER_MASK, 1, 60, &nval, inmask) != 0) {
    SCTPUT("Error reading the rebinned mask name");
    return flames_midas_fail();
  }

  // read output base name 
  if (SCKGETC(MBASENAME,1,60,&nval,basename)!=0) {
    // problems reading MBASENAME 
    SCTPUT("Error reading the base name for output spectra");
    return flames_midas_fail();
  }
  
  // initialise MASKTHRES from keyword 
  if (SCKRDD(MASKTHRES, 1, 1, &nval, &maskthres, &unit, &null) != 0) {
    // problems reading MASKTHRES 
    SCTPUT("Error reading the MASKTHRES keyword");
    return flames_midas_fail();
  }
  */


  maskthres=*MASKTHRES;
  strcpy(infile,INTER_IMA);
  strcpy(insigma,INTER_SIGMA);
  strcpy(inmask,INTER_MASK);
  strcpy(basename,MBASENAME);




  if (stripfitsext(basename, mbasename) != NOERR) {
    SCTPUT("Error stripping basename extension");
    return flames_midas_fail();
  }


  /* open the spectrum to be merged */
  if (SCFOPN(infile, FLAMESDATATYPE, 0, F_IMA_TYPE, &infileid) != 0) {
    SCTPUT("Error opening the rebinned spectrum");
    return flames_midas_fail();
  }


  /* read the main descriptor and make sure they are what they are 
     expected to be */
  if (SCDRDI(infileid, "NAXIS", 1, 1, &nval, &naxis, &unit, &null)!=0) {
    SCTPUT("Error getting NAXIS from spectrum");
    return flames_midas_fail();
  }

  if (nval<1) {
    SCTPUT("Error getting NAXIS from spectrum");
    return flames_midas_fail();
  }

  if (naxis != 2) {
    SCTPUT("Error: wrong spectrum dimentions");
    return flames_midas_fail();
  }


  if (SCDRDD(infileid, "START",1, 2, &nval, start, &unit, &null)!=0) {
    SCTPUT("Error getting START from spectrum");
    return flames_midas_fail();
  }
  if (nval<2) {
    SCTPUT("Error getting START from spectrum");
    return flames_midas_fail();
  }


  if (SCDRDD(infileid, "STEP", 1, 2, &nval, step, &unit, &null)!=0) {
    SCTPUT("Error getting STEP from spectrum");
    return flames_midas_fail();
  }
  if (nval<2) {
    SCTPUT("Error getting STEP from spectrum");
    return flames_midas_fail();
  }

  if (SCDRDI(infileid, "NPIX", 1, 2, &nval, npix, &unit, &null)!=0) {
    SCTPUT("Error getting STEP from spectrum");
    return flames_midas_fail();
  }
  if (nval<2) {
    SCTPUT("Error getting NPIX from spectrum");
    return flames_midas_fail();
  }

  /* now we know how large we need wstart and nptot to be, allocate them */
  wstart = dvector(0, npix[1]-1);
  nptot = ivector(0,npix[1]-1);
  wstart2 = dvector(0, npix[1]-1);
  nptot2 = ivector(0,npix[1]-1);
  spectrum = fdmatrix(0,npix[1]-1, 0, npix[0]-1);
  sigma = fdmatrix(0,npix[1]-1, 0, npix[0]-1);
  mask = matrix(0,npix[1]-1, 0, npix[0]-1);
  vecspectrum = spectrum[0];
  vecsigma = sigma[0];
  vecmask = mask[0];


  if (SCDRDD(infileid, "WSTART", 1, npix[1], &nval, wstart, &unit, &null)!=0) {
    SCTPUT("Error reading WSTART from spectrum");
    return flames_midas_fail();
  }
  if (nval<npix[1]) {
    SCTPUT("Error reading WSTART: less values than expected");
    return flames_midas_fail();
  }

  if (SCDRDI(infileid, "NPTOT", 1, npix[1], &nval, nptot, &unit, &null)!=0) {
    SCTPUT("Error reading NPTOT from spectrum");
    return flames_midas_fail();
  }
  if (nval<npix[1]) {
    SCTPUT("Error reading NPTOT: less values than expected");
    return flames_midas_fail();
  }

  if (SCFGET(infileid, 1, npix[0]*npix[1], &nval, (char *) spectrum[0])!=0) {
    SCTPUT("Error reading spectrum");
    return flames_midas_fail();
  }
  if (nval<(npix[0]*npix[1])) {
    SCTPUT("Error reading spectrum: less values than expected");
    return flames_midas_fail();
  }


  /* now do the same with the variance file */
  if (SCFOPN(insigma, FLAMESDATATYPE, 0, F_IMA_TYPE, &insigmaid) != 0) {
    SCTPUT("Error opening the rebinned variances");
    return flames_midas_fail();
  }

  /* read the main descriptor and make sure they are what they are 
     expected to be */
  if (SCDRDI(insigmaid, "NAXIS", 1, 1, &nval, &naxis, &unit, &null)!=0) {
    SCTPUT("Error getting NAXIS from variances file");
    return flames_midas_fail();
  }
  if (nval<1) {
    SCTPUT("Error getting NAXIS from spectrum");
    return flames_midas_fail();
  }
  if (naxis != 2) {
    SCTPUT("Error: wrong variances dimentions");
    return flames_midas_fail();
  }

  if (SCDRDD(insigmaid, "START", 1, 2, &nval, start2, &unit, &null)!=0) {
    SCTPUT("Error getting START from variances");
    return flames_midas_fail();
  }
  if (nval<2) {
    SCTPUT("Error getting START from spectrum");
    return flames_midas_fail();
  }
  if ((start2[0] != start[0]) || (start2[1] != start[1])) {
    SCTPUT("Error: mismatch between spectrum and variance START");
    return flames_midas_fail();
  }


  if (SCDRDD(insigmaid, "STEP", 1, 2, &nval, step2, &unit, &null)!=0) {
    SCTPUT("Error getting STEP from variances");
    return flames_midas_fail();
  }
  if (nval<2) {
    SCTPUT("Error getting START from spectrum");
    return flames_midas_fail();
  }
  if ((step2[0] != step[0]) || (step2[1] != step[1])) {
    SCTPUT("Error: mismatch between spectrum and variance STEP");
    return flames_midas_fail();
  }


  if (SCDRDI(insigmaid, "NPIX", 1, 2, &nval, npix2, &unit, &null)!=0) {
    SCTPUT("Error getting NPIX from variances");
    return flames_midas_fail();
  }
  if (nval<2) {
    SCTPUT("Error getting NPIX from variances");
    return flames_midas_fail();
  }
  if ((npix2[0] != npix[0]) || (npix2[1] != npix[1])) {
    SCTPUT("Error: mismatch between spectrum and variance NPIX");
    return flames_midas_fail();
  }


  if (SCDRDD(insigmaid, "WSTART", 1, npix[1], &nval, wstart2, &unit, 
         &null)!=0) {
    SCTPUT("Error reading WSTART from variances");
    return flames_midas_fail();
  }
  if (nval<npix[1]) {
    SCTPUT("Error reading WSTART: less values than expected");
    return flames_midas_fail();
  }
  for (i=0; i<=(npix[1]-1); i++) {
    if (wstart2[i] != wstart[i]) {
      SCTPUT("Error: mismatch between spectrum and variance WSTART");
      return flames_midas_fail();
    }
  }


  if (SCDRDI(insigmaid, "NPTOT", 1, npix[1], &nval, nptot2, &unit, &null)!=0) {
    SCTPUT("Error reading NPTOT from spectrum");
    return flames_midas_fail();
  }
  if (nval<npix[1]) {
    SCTPUT("Error reading NPTOT: less values than expected");
    return flames_midas_fail();
  }
  for (i=0; i<=(npix[1]-1); i++) {
    if (nptot2[i] != nptot[i]) {
      SCTPUT("Error: mismatch between spectrum and variance NPTOT");
      return flames_midas_fail();
    }
  }

  if (SCFGET(insigmaid, 1, npix[0]*npix[1], &nval, (char *) sigma[0])!=0) {
    SCTPUT("Error reading variances");
    return flames_midas_fail();
  }
  if (nval<(npix[0]*npix[1])) {
    SCTPUT("Error reading variances: less values than expected");
    return flames_midas_fail();
  }

  /* We can close the insigma frame */
  if (SCFCLO(insigmaid)!=0) {
    SCTPUT("Error closing variance frame");
    return flames_midas_fail();
  }



  /* now do the same with the mask file */
  /* the mask file was rebinned from an I1 data type, but MIDAS promotes
     it to an R4 data type */
  if (SCFOPN(inmask, D_R4_FORMAT, 0, F_IMA_TYPE, &inmaskid) != 0) {
    SCTPUT("Error opening the rebinned mask");
    return flames_midas_fail();
  }

  /* read the main descriptor and make sure they are what they are 
     expected to be */
  if (SCDRDI(inmaskid, "NAXIS", 1, 1, &nval, &naxis, &unit, &null)!=0) {
    SCTPUT("Error getting NAXIS from mask file");
    return flames_midas_fail();
  }
  if (nval<1) {
    SCTPUT("Error getting NAXIS from spectrum");
    return flames_midas_fail();
  }
  if (naxis != 2) {
    SCTPUT("Error: wrong mask dimentions");
    return flames_midas_fail();
  }


  if (SCDRDD(inmaskid, "START", 1, 2, &nval, start2, &unit, &null)!=0) {
    SCTPUT("Error getting START from mask");
    return flames_midas_fail();
  }
  if (nval<2) {
    SCTPUT("Error getting START from mask");
    return flames_midas_fail();
  }
  if ((start2[0] != start[0]) || (start2[1] != start[1])) {
    SCTPUT("Error: mismatch between spectrum and mask START");
    return flames_midas_fail();
  }

  if (SCDRDD(inmaskid, "STEP", 1, 2, &nval, step2, &unit, &null)!=0) {
    SCTPUT("Error getting STEP from mask");
    return flames_midas_fail();
  }
  if (nval<2) {
    SCTPUT("Error getting STEP from mask");
    return flames_midas_fail();
  }
  if ((step2[0] != step[0]) || (step2[1] != step[1])) {
    SCTPUT("Error: mismatch between spectrum and mask STEP");
    return flames_midas_fail();
  }

  if (SCDRDI(inmaskid, "NPIX", 1, 2, &nval, npix2, &unit, &null)!=0) {
    SCTPUT("Error getting STEP from mask");
    return flames_midas_fail();
  }
  if (nval<2) {
    SCTPUT("Error getting NPIX from mask");
    return flames_midas_fail();
  }
  if ((npix2[0] != npix[0]) || (npix2[1] != npix[1])) {
    SCTPUT("Error: mismatch between spectrum and mask NPIX");
    return flames_midas_fail();
  }


  if (SCDRDD(inmaskid, "WSTART", 1, npix[1], &nval, wstart2, &unit, 
         &null)!=0) {
    SCTPUT("Error reading WSTART from mask");
    return flames_midas_fail();
  }
  if (nval<npix[1]) {
    SCTPUT("Error reading WSTART: less values than expected");
    return flames_midas_fail();
  }
  for (i=0; i<=(npix[1]-1); i++) {
    if (wstart2[i] != wstart[i]) {
      SCTPUT("Error: mismatch between spectrum and mask WSTART");
      return flames_midas_fail();
    }
  }


  if (SCDRDI(inmaskid, "NPTOT", 1, npix[1], &nval, nptot2, &unit, &null)!=0) {
    SCTPUT("Error reading NPTOT from mask");
    return flames_midas_fail();
  }
  if (nval<npix[1]) {
    SCTPUT("Error reading NPTOT: less values than expected");
    return flames_midas_fail();
  }
  for (i=0; i<=(npix[1]-1); i++) {
    if (nptot2[i] != nptot[i]) {
      SCTPUT("Error: mismatch between spectrum and mask NPTOT");
      return flames_midas_fail();
    }
  }

  if (SCFGET(inmaskid, 1, npix[0]*npix[1], &nval, (char *) mask[0])!=0) {
    SCTPUT("Error reading mask");
    return flames_midas_fail();
  }
  if (nval<(npix[0]*npix[1])) {
    SCTPUT("Error reading mask: less values than expected");
    return flames_midas_fail();
  }

  /* We can close the insigma frame */
  if (SCFCLO(insigmaid)!=0) {
    SCTPUT("Error closing mask frame");
    return flames_midas_fail();
  }



  /* ok, now go ahead and find the merged frame limits */
  mstart = wstart[0];
  mstep = step[0];
  /* In principle, there should be no reason to truncate to nearest integer, 
     since it ought to be an exact integer, but just in case */
  mnpix = ((int) floor(((wstart[npix[1]-1]-wstart[0])/step[0])+0.5)) + 
    nptot[npix[1]-1];

  /* now I can allocate the merged vectors */
  mspectrum = fdvector(0,mnpix-1);
  msigma = fdvector(0,mnpix-1);
  mmask = fmvector(0,mnpix-1);
  /* initialise the above vectors */
  for (j=0; j<=(mnpix-1); j++) {
    mspectrum[j] = 0;
    msigma[j] = 0;
    mmask[j] = 0;
  }


  /* begin the actual merging
     npix[1]=No of orders
     nptot[i]=No of pixels per order
   */
  int jdelta1=delta1/step[0];
  int jdelta2=delta2/step[0];

  for (i=0; i<=(npix[1]-1); i++) {
    /* the i-th order begins at joffset-th pixel in the rebinned frame */
    joffset = ((int) floor(((wstart[i]-wstart[0])/step[0])+0.5));
    for (j=jdelta1; j<=(nptot[i]-1)-jdelta2; j++) {
      ijindex = (i*npix[0])+j;
      /* is this a good pixel? */
      if (vecmask[ijindex] >= maskthres) {
    shiftedj = j+joffset;
    /* yes, hence use it */
    weight = 1/vecsigma[ijindex];
    mspectrum[shiftedj] += weight*vecspectrum[ijindex];
    /* at the moment, use msigma to hold the normalisation factors to 
       be used later */
    msigma[shiftedj] += weight;
    /* we have at least this value at this wavelength, hence this is a 
       good pixel */
    mmask[shiftedj] = 1;
      }
    }
  }


  /* to wrap up, normalise the merged spectrum and compute the final
     merged variance */
  for (j=0; j<=(mnpix-1); j++) {
    /* is this a good pixel? */
    if (mmask[j] == 1) {
      /* yes, hence normalise it */
      mspectrum[j] /= msigma[j];
      /* compute the variance */
      msigma[j] = 1/msigma[j];
    }
  }


  /* that's all, folks! Time to write to disk, clean up and exit */
  sprintf(mspecname, "%s.fits", mbasename);
  sprintf(msigmaname, "%s_sigma.fits", mbasename);
  sprintf(mmaskname, "%s_mask.fits", mbasename);
  mnaxis = 1;
  if (SCFCRE(mspecname, FLAMESDATATYPE, F_O_MODE, F_IMA_TYPE, mnpix, 
         &mspecid) != 0) {
    /* could not create the merged spectrum file */
    SCTPUT("Error creating merged spectrum file");
    return flames_midas_fail();
  }
  /* write the spectrum itself */
  if (SCFPUT(mspecid, 1, mnpix, (char *) mspectrum) != 0) {
    SCTPUT("Error writing merged spectrum");
  }
  /* write standard descriptors of file */
  if (SCDWRC(mspecid, "IDENT", 1, ident, 1, 72, &unit)) {
    SCFCLO(mspecid); 
    return flames_midas_fail();
  }
  if (SCDWRI(mspecid, "NAXIS", &mnaxis, 1, 1, &unit)) {
    SCFCLO(mspecid); 
    return flames_midas_fail();
  }
  if (SCDWRI(mspecid, "NPIX", &mnpix, 1, 1, &unit)) {
    SCFCLO(mspecid); 
    return flames_midas_fail();
  }
  if (SCDWRD(mspecid, "START", &mstart, 1, 1, &unit)) {
    /* error writing descriptor */
    SCFCLO(mspecid); 
    return flames_midas_fail();
  }
  if (SCDWRD(mspecid, "STEP", &mstep, 1, 1, &unit)) { 
    SCFCLO(mspecid); 
    return flames_midas_fail();
  }
  if (SCDWRC(mspecid, "CUNIT", 1, cunit[0], 1, 32, &unit)) {
    SCFCLO(mspecid); 
    return flames_midas_fail();
  }

  minimum = mspectrum[0];
  maximum = mspectrum[0];
  for (j=0; j<=(mnpix-1); j++) {
    maximum = mspectrum[j] > maximum ? mspectrum[j] : maximum;
    minimum = mspectrum[j] < minimum ? mspectrum[j] : minimum;
  }
  cuts[2] = (float) minimum;
  cuts[3] = (float) maximum;
  if (SCDWRR(mspecid, "LHCUTS", cuts, 1, 4, &unit)) {
    SCFCLO(mspecid); 
    return flames_midas_fail();
  }
  
  /* write the sigma file name as a descriptor of the data file */
  if (SCDWRC(mspecid, "SIGMAFRAME", 1, msigmaname, 1, 80, &unit)) {
    /* error writing descriptor */
    SCFCLO(mspecid); 
    return flames_midas_fail();
  }
  
  /* write the extracted columns file name as a descriptor of the data file */
  if (SCDWRC(mspecid, "MASKFRAME", 1, mmaskname, 1, 80, &unit)) {
    /* error writing descriptor */
    SCFCLO(mspecid); 
    return flames_midas_fail();
  }

  /* close the spectrum */
  if (SCFCLO(mspecid) != 0) {
    /* error closing frame */
    SCTPUT("Warning: the merged spectrum could not be closed");
  }



  /* write the merged variance */
  if (SCFCRE(msigmaname, FLAMESDATATYPE, F_O_MODE, F_IMA_TYPE, mnpix, 
         &msigmaid) != 0) {
    /* could not create the merged sigma file */
    SCTPUT("Error creating merged sigma file");
    return flames_midas_fail();
  }
  /* write the variance itself */
  if (SCFPUT(msigmaid, 1, mnpix, (char *) msigma) != 0) {
    SCTPUT("Error writing merged variance");
  }
  /* write standard descriptors of file */
  if (SCDWRC(msigmaid, "IDENT", 1, ident, 1, 72, &unit)) {
    SCFCLO(msigmaid); 
    return flames_midas_fail();
  }
  if (SCDWRI(msigmaid, "NAXIS", &mnaxis, 1, 1, &unit)) {
    SCFCLO(msigmaid); 
    return flames_midas_fail();
  }
  if (SCDWRI(msigmaid, "NPIX", &mnpix, 1, 1, &unit)) {
    SCFCLO(msigmaid); 
    return flames_midas_fail();
  }
  if (SCDWRD(msigmaid, "START", &mstart, 1, 1, &unit)) {
    /* error writing descriptor */
    SCFCLO(msigmaid); 
    return flames_midas_fail();
  }
  if (SCDWRD(msigmaid, "STEP", &mstep, 1, 1, &unit)) { 
    SCFCLO(msigmaid); 
    return flames_midas_fail();
  }
  if (SCDWRC(msigmaid, "CUNIT", 1, cunit[0], 1, 32, &unit)) {
    SCFCLO(msigmaid); 
    return flames_midas_fail();
  }
  minimum = msigma[0];
  maximum = msigma[0];
  for (j=0; j<=(mnpix-1); j++) {
    maximum = msigma[j] > maximum ? msigma[j] : maximum;
    minimum = msigma[j] < minimum ? msigma[j] : minimum;
  }
  cuts[2] = (float) minimum;
  cuts[3] = (float) maximum;
  if (SCDWRR(msigmaid, "LHCUTS", cuts, 1, 4, &unit)) {
    SCFCLO(msigmaid); 
    return flames_midas_fail();
  }
  
 
  /* write the sigma file name as a descriptor of the data file */
  if (SCDWRC(msigmaid, "SPECTRUMFRAME", 1, mspecname, 1, 80, &unit)) {
    /* error writing descriptor */
    SCFCLO(msigmaid); 
    return flames_midas_fail();
  }
  
  /* close the spectrum */
  if (SCFCLO(msigmaid) != 0) {
    /* error closing frame */
    SCTPUT("Warning: the merged sigma could not be closed");
  }


  /* write the merged mask */
  if (SCFCRE(mmaskname, FLAMESMASKTYPE, F_O_MODE, F_IMA_TYPE, mnpix, 
         &mmaskid) != 0) {
    /* could not create the merged mask file */
    SCTPUT("Error creating merged mask file");
    return flames_midas_fail();
  }
  /* write the variance itself */
  if (SCFPUT(mmaskid, 1, mnpix, (char *) mmask) != 0) {
    SCTPUT("Error writing merged mask");
  }
  /* write standard descriptors of file */
  if (SCDWRC(mmaskid, "IDENT", 1, ident, 1, 72, &unit)) {
    SCFCLO(mmaskid); 
    return flames_midas_fail();
  }
  if (SCDWRI(mmaskid, "NAXIS", &mnaxis, 1, 1, &unit)) {
    SCFCLO(mmaskid); 
    return flames_midas_fail();
  }
  if (SCDWRI(mmaskid, "NPIX", &mnpix, 1, 1, &unit)) {
    SCFCLO(mmaskid); 
    return flames_midas_fail();
  }
  if (SCDWRD(mmaskid, "START", &mstart, 1, 1, &unit)) {
    /* error writing descriptor */
    SCFCLO(mmaskid); 
    return flames_midas_fail();
  }
  if (SCDWRD(mmaskid, "STEP", &mstep, 1, 1, &unit)) { 
    SCFCLO(mmaskid); 
    return flames_midas_fail();
  }
  if (SCDWRC(mmaskid, "CUNIT", 1, cunit[0], 1, 32, &unit)) {
    SCFCLO(mmaskid); 
    return flames_midas_fail();
  }
  cuts[2] = 0;
  cuts[3] = 1;
  if (SCDWRR(mmaskid, "LHCUTS", cuts, 1, 4, &unit)) {
    SCFCLO(mmaskid); 
    return flames_midas_fail();
  }
  

  /* write the spetrum file name as a descriptor of the data file */
  if (SCDWRC(mmaskid, "SPECTRUMFRAME", 1, mspecname, 1, 80, &unit)) {
    /* error writing descriptor */
    SCFCLO(mmaskid); 
    return flames_midas_fail();
  }
  
  /* close the spectrum */
  if (SCFCLO(mmaskid) != 0) {
    /* error closing frame */
    SCTPUT("Warning: the merged mask could not be closed");
  }


  /* everything written, clean up and get out */
  free_dvector(wstart, 0, npix[1]-1);
  free_ivector(nptot, 0,npix[1]-1);
  free_dvector(wstart2, 0,npix[1]-1);
  free_ivector(nptot2, 0,npix[1]-1);
  free_fdmatrix(spectrum, 0,npix[1]-1, 0, npix[0]-1);
  free_fdmatrix(sigma, 0,npix[1]-1, 0, npix[0]-1);
  free_matrix(mask, 0,npix[1]-1, 0, npix[0]-1);
  free_fdvector(mspectrum, 0,mnpix-1);
  free_fdvector(msigma, 0,mnpix-1);
  free_fmvector(mmask, 0,mnpix-1);

  return SCSEPI();

}
