/*===========================================================================
  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
===========================================================================*/
/* Program  : readallff.c                                                  */
/* Author   : G. Mulas  -  ITAL_FLAMES Consortium                          */
/* Date     :                                                              */
/*                                                                         */
/* Purpose  : Missing                                                      */
/*                                                                         */
/*                                                                         */
/* Input:  see interface                                                   */ 
/*                                                                      */
/* Output:                                                              */
/*                                                                         */
/* DRS Functions called:                                                   */
/* none                                                                    */ 
/*                                                                         */ 
/* Pseudocode:                                                             */
/* Missing                                                                 */ 
/*                                                                         */ 
/* Version  :                                                              */
/* Last modification date: 2002/08/05                                      */
/* Who     When        Why                Where                            */
/* AMo     02-08-05   Add header         header                            */
/*-------------------------------------------------------------------------*/

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

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <math.h>
#include <flames_midas_def.h>
#include <flames_readallff.h>
#include <flames_uves.h>
#include <flames_dfs.h>
#include <flames_checksize3.h>
#include <flames_newmatrix.h>
#include <flames_allocallflats.h>
#include <uves_msg.h>
#include <uves_dump.h>


flames_err 
readallff(const cpl_frameset *catname, allflats *myflats)
{
    int32_t iframe=0;
    int32_t ifibre=0;
    int32_t ncommon=0;
    int32_t nnormal=0;
    int32_t nnsigma=0;
    char filename[CATREC_LEN+1];
    char identifier[CATREC_LEN+1];
    int status=0;
    int entrynum=0;
    char normalname[CATREC_LEN+1];
    char nsigmaname[CATREC_LEN+1];
    char commoname[CATREC_LEN+1];
    int commonid=0;
    int normid=0;
    int nsigid=0;
    int frameid=0;
    int sigmaid=0;
    int badid=0;
    int ibuf=0;
    int actvals=0;
    int actsize=0;
    int unit=0;
    int null=0;
    int *fibres=0;
    char* fixed_name=NULL;
    int32_t ****longarray=0;
    //Fixme: added to fix a problem with descriptors
    //int comid=0;
    double start[2]={1.0,1.0};

    frame_mask *fmvecbuf1=0;
    int32_t *lvecbuf1=0;
    int32_t *lvecbuf2=0;
    int32_t *lvecbuf3=0;
    int32_t *lvecbuf4=0;
    int32_t *lvecbuf5=0;
    int32_t maxiorderifibreixindex=0;
    int32_t iorderifibreixindex=0;

    memset(filename, '\0', CATREC_LEN+1);
    memset(identifier, '\0', CATREC_LEN+1);
    memset(normalname, '\0', CATREC_LEN+1);
    memset(nsigmaname, '\0', CATREC_LEN+1);
    memset(commoname, '\0', CATREC_LEN+1);

    myflats->nflats = 0;
    ncommon = 0;
    nnormal = 0;
    nnsigma = 0;
    /* first open the catalog, count the fibre FF frames, the normalisation
     frame(s) and the common 4D frame present */
    entrynum = 0;

    do {

        if ((status = SCCGET(catname, 1, filename, identifier, &entrynum)) != 0) {
            /* error getting catalog entry */
            return(MAREMMA);
        }
        uves_msg_debug("file=%s with identifier=%s",filename,identifier);
        /* did I get a valid catalog entry? */
        if (filename[0] != ' ') {
            /* is this a int32_t slit FF frame? */
            uves_msg_debug(">%s<\n","Cleaned fibre FF");

            if(strncmp(identifier, "Cleaned fibre FF",16) == 0) {
                //if(strncmp(identifier, "FIB_FF_DT",9) == 0) {
                myflats->nflats++;
            }

            /* is this a normalisation frame? */
            if(strncmp(identifier, "Normalisation data for fibre FF",31) == 0) {
                //if(strncmp(identifier, "FIB_FF_NOR",10) == 0) {
                nnormal++;
                strcpy(normalname, filename);
            }

            /* is this a normalisation frame? */
            if(strncmp(identifier, "Normalisation sigmas for fibre FF",33) == 0) {
                //if(strncmp(identifier, "FIB_FF_NSG",10) == 0) {
                nnsigma++;
                strcpy(nsigmaname, filename);
            }

            /* is this a common frame? */
            if(strncmp(identifier, "Common data for fibre FF",24) == 0) {
                //if(strncmp(identifier, "FIB_FF_COM",10) == 0) {
                //FixMe added to fix a problem of missing descriptors in com fib frame
                //status = SCFOPN(filename, FLAMESDATATYPE, 0, F_IMA_TYPE, &comid);
                //SCDWRC(comid, "SHIFTABLE",  1, "y", 1, 1, &unit);
                //SCDWRC(comid, "NORMALISED", 1, "y", 1, 1, &unit);
                //SCFCLO(comid);
                ncommon++;
                strcpy(commoname, filename);
            }

        }

    } while (filename[0] != ' ');


    /* did I get at least 1 FF frame name? */
    if (myflats->nflats < 1) {
        /* I need at least 1 FF frame! */
        return(MAREMMA);
    }


    /* did I get exactly 1 normalisation frame and common frame name? */
    if (nnormal != 1) {
        /* I need exactly 1 normalisation frame name! */
        return(MAREMMA);
    }


    if (nnsigma != 1) {
        /* I need exactly 1 normalisation sigmas frame name! */
        return(MAREMMA);
    }

    if (ncommon != 1) {
        /* I need exactly 1 common frame name! */
        return(MAREMMA);
    }

    /* open the common frame to get the descriptors */
    if ((status = SCFOPN(commoname, D_I4_FORMAT, 0, F_IMA_TYPE,
                    &commonid)) != 0) {
        /* could not open the frame */
        return(MAREMMA);
    }
    /* read the relevant information from the frame */
    if ((status = SCDRDI(commonid, "NFLATS", 1, 1, &actvals, &ibuf,
                    &unit, &null)) != 0) {
        /* problems reading NFLATS: complain... */
        return(MAREMMA);
    }
    if (myflats->nflats != ibuf) {
        /* mismatch between catalog and descriptors, abort */
        return(MAREMMA);
    }

    if ((status = SCDRDI(commonid, "ROWS", 1, 1, &actvals, &ibuf,
                    &unit, &null)) != 0) {
        /* problems reading ROWS: complain... */
        return(MAREMMA);
    }

    myflats->subrows = (int32_t) ibuf;
    if ((status = SCDRDI(commonid, "COLS", 1, 1, &actvals, &ibuf,
                    &unit, &null)) != 0) {
        /* problems reading COLS: complain... */
        return(MAREMMA);
    }

    myflats->subcols = (int32_t) ibuf;
    if ((status = SCDRDD(commonid, "STARTX", 1, 1, &actvals,
                    &myflats->substartx, &unit, &null)) != 0) {
        /* problems reading STEPX: complain... */
        return(MAREMMA);
    }
    if ((status = SCDRDD(commonid, "STARTY", 1, 1, &actvals,
                    &myflats->substarty, &unit, &null)) != 0) {
        /* problems reading STEPY: complain... */
        return(MAREMMA);
    }
    if ((status = SCDRDD(commonid, "STEPX", 1, 1, &actvals,
                    &myflats->substepx, &unit, &null)) != 0) {
        /* problems reading STEPX: complain... */
        return(MAREMMA);
    }
    if ((status = SCDRDD(commonid, "STEPY", 1, 1, &actvals,
                    &myflats->substepy, &unit, &null)) != 0) {
        /* problems reading STEPY: complain... */
        return(MAREMMA);
    }

    if ((status = SCDRDC(commonid, "CHIPCHOICE", 1, 1, 1, &actvals,
                    &myflats->chipchoice, &unit, &null)) != 0) {
        /* problems reading CHIPCHOICE: complain... */
        return(MAREMMA);
    }
    if ((status = SCDRDD(commonid, "RON", 1, 1, &actvals,
                    &myflats->ron, &unit, &null)) != 0) {
        /* problems reading RON: complain... */
        return(MAREMMA);
    }
    if ((status = SCDRDD(commonid, "GAIN", 1, 1, &actvals,
                    &myflats->gain, &unit, &null)) != 0) {
        /* problems reading GAIN: complain... */
        return(MAREMMA);
    }
    if ((status = SCDRDI(commonid, "ORDERLIM", 1, 1, &actvals,
                    &myflats->firstorder, &unit, &null)) != 0) {
        /* problems reading FIRSTORDER: complain... */
        return(MAREMMA);
    }

    if ((status = SCDRDI(commonid, "ORDERLIM", 2, 1, &actvals,
                    &myflats->lastorder, &unit, &null)) != 0) {
        /* problems reading LASTORDER: complain... */
        return(MAREMMA);
    }
    if ((status = SCDRDI(commonid, "TAB_IN_OUT_OSHIFT", 1, 1, &actvals,
                    &myflats->tab_io_oshift, &unit, &null)) != 0) {
        /* problems reading LASTORDER: complain... */
        return(MAREMMA);
    }
    if ((status = SCDRDI(commonid, "MAXFIBRES", 1, 1, &actvals, &ibuf,
                    &unit, &null)) != 0) {
        /* problems reading COLS: complain... */
        return(MAREMMA);
    }
    myflats->maxfibres = (int32_t) ibuf;
    if ((status = SCDRDD(commonid, "PIXMAX", 1, 1, &actvals,
                    &myflats->pixmax, &unit, &null)) != 0) {
        /* problems reading GAIN: complain... */
        return(MAREMMA);
    }


    if ((status = SCDRDD(commonid, "HALFIBREWIDTH", 1, 1, &actvals,
                    &myflats->halfibrewidth, &unit, &null)) != 0) {
        /* problems reading GAIN: complain... */
        return(MAREMMA);
    }
    if ((status = SCDRDD(commonid, "MINFIBREFRAC", 1, 1, &actvals,
                    &myflats->minfibrefrac, &unit, &null)) != 0) {
        /* problems reading GAIN: complain... */
        return(MAREMMA);
    }
    if ((status = SCDRDI(commonid, "NUMFIBRES", 1, 1, &actvals, &ibuf,
                    &unit, &null)) != 0) {
        /* problems reading COLS: complain... */
        return(MAREMMA);
    }



    //Fixme: we suppressed the check on SHIFTABLE & NORMALIZED
    myflats->numfibres = (int32_t) ibuf;
    //if ((status = SCDRDC(commonid, "SHIFTABLE", 1, 1, 1, &actvals,
    //           &myflats->shiftable, &unit, &null)) != 0) {
    //  /* problems reading SHIFTABLE complain... */
    //  return(MAREMMA);
    //}
    myflats->shiftable='y';

    //if ((status = SCDRDC(commonid, "NORMALISED", 1, 1, 1, &actvals,
    //               &myflats->normalised, &unit, &null)) != 0) {
    //  /* problems reading NORMALISED complain... */
    //  return(MAREMMA);
    //
    //}
    myflats->normalised='y';


    /* allocate dynamic auxiliary vectors */
    fibres = ivector(0,myflats->maxfibres-1);

    /* allocate the arrays in the structure */
    if ((status = allocallflats(myflats)) != NOERR) {
        /* problem allocating internal arrays of myflats */
        return(MAREMMA);
    }

    /* read vectors from descriptors */
    if ((status = SCDRDI(commonid, "FIBREMASK", 1, myflats->maxfibres,
                    &actvals, myflats->fibremask, &unit, &null)) != 0) {
        /* problems reading COLS: complain... */
        return(MAREMMA);
    }

    if ((status = SCDRDI(commonid, "FIBRE2FRAME", 1, myflats->maxfibres,
                    &actvals, myflats->fibre2frame, &unit, &null)) != 0) {
        /* problems reading COLS: complain... */
        return(MAREMMA);
    }

    /* allocate the temporary 4D buffer for the data in the common frame
     itself */
    longarray = l4tensor(0, 2, 0, myflats->lastorder-myflats->firstorder,
                    0, myflats->maxfibres-1, 0, myflats->subcols-1);

    /* read the common frame into the buffer */
    if ((status =
                    SCFGET(commonid, 1,
                                    3*(myflats->lastorder-myflats->firstorder+1)*
                                    myflats->maxfibres*myflats->subcols, &actsize,
                                    (char *)(&longarray[0][0][0][0]))) != 0) {
        /* problems reading common frame: complain */
        return(MAREMMA);
    }
    else if (actsize != 3*(myflats->lastorder-myflats->firstorder+1)*
                    myflats->maxfibres*myflats->subcols) {
        /* I read fewer elements than expected: complain... */
        return(MAREMMA);
    }

    /* close the common frame */
    if ((status = SCFCLO(commonid)) != 0) {
        /* problems closing common frame */
        return(MAREMMA);
    }

    /* put values in the structure */
    lvecbuf1 = longarray[0][0][0];
    lvecbuf2 = longarray[1][0][0];
    lvecbuf3 = longarray[2][0][0];
    lvecbuf4 = myflats->lowfibrebounds[0][0];
    lvecbuf5 = myflats->highfibrebounds[0][0];
    fmvecbuf1 = myflats->goodfibres[0][0];

    memcpy(myflats->lowfibrebounds[0][0], longarray[0][0][0],
           (myflats->lastorder-myflats->firstorder+1)*
           myflats->maxfibres*myflats->subcols*sizeof(int32_t));
    memcpy(myflats->highfibrebounds[0][0], longarray[1][0][0],
           (myflats->lastorder-myflats->firstorder+1)*
           myflats->maxfibres*myflats->subcols*sizeof(int32_t));
    maxiorderifibreixindex = ((myflats->lastorder-myflats->firstorder+1)*
                    myflats->maxfibres*myflats->subcols)-1;


    for (iorderifibreixindex=0; iorderifibreixindex<=maxiorderifibreixindex;
                    iorderifibreixindex++) {
        fmvecbuf1[iorderifibreixindex] = (frame_mask)lvecbuf3[iorderifibreixindex];
    }

    /* free the buffer */
    free_l4tensor(longarray, 0, 2, 0, myflats->lastorder-myflats->firstorder,
                  0, myflats->maxfibres-1, 0, myflats->subcols-1);


    /* open the normalisation frame */
    if ((status = SCFOPN(normalname, FLAMESDATATYPE, 0, F_IMA_TYPE,
                    &normid)) != 0) {
        /* could not open the frame */
        return(MAREMMA);
    }

    /* read the normalisation frame */
    if ((status =
                    SCFGET(normid, 1,
                                    (myflats->lastorder-myflats->firstorder+1)*
                                    myflats->maxfibres*myflats->subcols, &actsize,
                                    (char *)&myflats->normfactors[0][0][0])) != 0) {
        /* problems reading common frame: complain */
        return(MAREMMA);
    }
    else if (actsize != (myflats->lastorder-myflats->firstorder+1)*
                    myflats->maxfibres*myflats->subcols) {
        /* I read fewer elements than expected: complain... */
        return(MAREMMA);
    }

    /* all right, close normalisation frame */
    if ((status = SCFCLO(normid)) != 0) {
        /* problems closing common frame */
        return(MAREMMA);
    }

    /* open the normalisation sigmas frame */
    if ((status = SCFOPN(nsigmaname, FLAMESDATATYPE, 0, F_IMA_TYPE,
                    &nsigid)) != 0) {
        /* could not open the frame */
        return(MAREMMA);
    }
    uves_msg_debug("lastorder=%d firstorder=%d subcols=%d maxfibres=%d",
                   myflats->lastorder,myflats->firstorder,myflats->subcols,
                   myflats->maxfibres);

    /* read the normalisation sigma frame */
    if ((status =
                    SCFGET(nsigid, 1,
                                    (myflats->lastorder-myflats->firstorder+1)*
                                    myflats->maxfibres*myflats->subcols, &actsize,
                                    (char *)&myflats->normsigmas[0][0][0])) != 0) {

        uves_msg_debug("check=%d vs=%d",(myflats->lastorder-myflats->firstorder+1)*
                        myflats->maxfibres*myflats->subcols,actsize);

        /* problems reading normsigma frame: complain */
        return(MAREMMA);
    }
    else if (actsize != (myflats->lastorder-myflats->firstorder+1)*
                    myflats->maxfibres*myflats->subcols) {
        /* I read fewer elements than expected: complain... */
        return(MAREMMA);
    }


    /* all right, close normalisation sigmas frame */
    if ((status = SCFCLO(nsigid)) != 0) {
        /* problems closing common frame */
        return(MAREMMA);
    }

    /* rescan the catalog from the beginning and, this time, read all
     fibre FF frame names */
    iframe = 0;
    entrynum = 0;
    do {
        if ((status = SCCGET(catname, 1, filename, identifier, &entrynum)) != 0) {
            /* error getting catalog entry */
            return(MAREMMA);
        }
        /* did I get a valid catalog entry? */
        if (filename[0] != ' ') {
            /* is this a fibre FF frame? */
            if(strncmp(identifier, "Cleaned fibre FF",16) == 0) {
                //if(strstr(identifier, "FIB_FF_DT") != NULL) {
                strcpy(myflats->flatdata[iframe].framename, filename);
                iframe++;
            }
        }
    } while ((filename[0] != ' ') && (iframe <= myflats->nflats-1));


    for (iframe=0; iframe<=(myflats->nflats-1); iframe++) {

        /* open the data frame */
        if ((status = SCFOPN(myflats->flatdata[iframe].framename,
                        FLAMESDATATYPE, 0, F_IMA_TYPE, &frameid)) != 0) {
            /* could not open the frame */
            return(MAREMMA);
        }

        /* do some consistency checks */
        /*
    //amodigli: added to fix descriptor START:
    //Midas SPLIT/UVES allways set START to 1-1
    //CPL not. And Bound slitff have -49 on CRPIX1-CRVAL1
    //As bound files are not images we cannor use 
    //flames_reset_crval_to_one, thus we need to modify such 
    //descriptor here
    if(SCDWRD(frameid, "START", start, 1, 2, &unit)) {
        SCFCLO(frameid);
        uves_msg_error("setting START");
         return MAREMMA;
    }
         */

        if (checksize3(frameid, myflats) != NOERR) {
            /* the file dimensions do not match */
            return(MAREMMA);
        }


        /* read the data frame */
        if ((status =
                        SCFGET(frameid, 1, myflats->subcols*myflats->subrows,
                                        &actsize, (char *) &myflats->flatdata[iframe].data[0][0]))
                        != 0) {
            /* error reading frame data */
            return(MAREMMA);
        }


        if (actsize != myflats->subcols*myflats->subrows) {
            /* wrong number of elements read */
            return(MAREMMA);
        }



        /* read frame-specific data from descriptors */
        if ((status = SCDRDD(frameid, "YSHIFT", 1, 1, &actvals,
                        &myflats->flatdata[iframe].yshift, &unit,
                        &null)) != 0) {
            /* problems reading YSHIFT: complain... */
            return(MAREMMA);
        }


        if ((status = SCDRDI(frameid, "NUMFIBRES", 1, 1, &actvals,
                        &ibuf, &unit, &null)) != 0) {
            /* problems reading NUMFIBRES: complain... */
            return(MAREMMA);
        }
        myflats->flatdata[iframe].numfibres = (int32_t) ibuf;


        if ((status = SCDRDI(frameid, "FIBRES", 1, myflats->maxfibres,
                        &actvals, fibres, &unit, &null)) != 0) {
            /* problems reading FIBRES: complain... */
            return(MAREMMA);
        }


        for(ifibre=0; ifibre<=myflats->flatdata[iframe].numfibres-1; ifibre++){
            myflats->flatdata[iframe].fibres[ifibre] =
                            (int32_t) fibres[ifibre];
        }


        for(; ifibre<=myflats->maxfibres-1; ifibre++){
            myflats->flatdata[iframe].fibres[ifibre] = 0;
        }



        /* read the name of the sigma frame */
        if ((status = SCDGETC(frameid, "SIGMAFILE", 1, CATREC_LEN, &actvals,
                        filename)) != 0) {
            /* problems reading sigma file name from descriptor */
        }


        //AMo: we fix possible .bdf estention
        fixed_name=flames_fix_estention(filename);
        strcpy(filename,fixed_name);
        cpl_free(fixed_name);
        /* open the sigma frame */
        if ((status = SCFOPN(filename, FLAMESDATATYPE, 0, F_IMA_TYPE,
                        &sigmaid)) != 0) {
            /* could not open the frame */
            return(MAREMMA);
        }


        /*
   //amodigli: added to fix descriptor START:
    //Midas SPLIT/UVES allways set START to 1-1
    //CPL not. And Bound slitff have -49 on CRPIX1-CRVAL1
    //As bound files are not images we cannor use 
    //flames_reset_crval_to_one, thus we need to modify such 
    //descriptor here
    if(SCDWRD(sigmaid, "START", start, 1, 2, &unit)) {
        SCFCLO(sigmaid);
        uves_msg_error("setting START");
         return MAREMMA;
    }
         */

        strcpy(myflats->flatdata[iframe].sigmaname, filename);
        /* do some consistency checks */
        if (checksize3(sigmaid, myflats) != NOERR) {
            /* the file dimensions do not match */
            return(MAREMMA);
        }


        /* read the frame */
        if ((status =
                        SCFGET(sigmaid, 1, myflats->subcols*myflats->subrows,
                                        &actsize, (char *) &myflats->flatdata[iframe].sigma[0][0]))
                        != 0) {
            /* error reading frame sigma */
            return(MAREMMA);
        }

        if (actsize != myflats->subcols*myflats->subrows) {
            /* wrong number of elements read */
            return(MAREMMA);
        }

        /* close the sigma frame */
        if ((status = SCFCLO(sigmaid)) != 0) {
            /* problems closing sigma frame */
            return(MAREMMA);
        }

        /* read the name of the badpixel frame */
        if ((status = SCDGETC(frameid, "BADPIXELFILE", 1, CATREC_LEN,
                        &actvals, filename)) != 0) {
            /* problems reading badpixel file name from descriptor */
        }

        //AMo: we fix possible .bdf estention
        fixed_name=NULL;
        fixed_name=flames_fix_estention(filename);
        strcpy(filename,fixed_name);
        cpl_free(fixed_name);

        /* open the sigma frame */
        if ((status = SCFOPN(filename, FLAMESMASKTYPE, 0, F_IMA_TYPE,
                        &badid)) != 0) {
            /* could not open the frame */
            return(MAREMMA);
        }


        //AMo: added to fix descriptor START
        if(SCDWRD(badid, "START", start, 1, 2, &unit)) {
            SCFCLO(badid);
            uves_msg_error("setting START");
            return MAREMMA;
        }


        /*
   //amodigli: added to fix descriptor START:
    //Midas SPLIT/UVES allways set START to 1-1
    //CPL not. And Bound slitff have -49 on CRPIX1-CRVAL1
    //As bound files are not images we cannor use 
    //flames_reset_crval_to_one, thus we need to modify such 
    //descriptor here
    if(SCDWRD(badid, "START", start, 1, 2, &unit)) {
        SCFCLO(badid);
        uves_msg_error("setting START");
         return MAREMMA;
    }
         */

        strcpy(myflats->flatdata[iframe].badname, filename);
        /* do some consistency checks */
        if (checksize3(badid, myflats) != NOERR) {
            /* the file dimensions do not match */
            return(MAREMMA);
        }

        /* read the bad pixel frame */
        if ((status = SCFGET(badid, 1, myflats->subcols*myflats->subrows,
                        &actsize,
                        (char *) &myflats->flatdata[iframe].badpixel[0][0]))
                        != 0) {
            /* error reading frame badpixel */
            return(MAREMMA);
        }

        if (actsize != myflats->subcols*myflats->subrows) {
            /* wrong number of elements read */
            return(MAREMMA);
        }


        /* close the badpixel frame */
        if ((status = SCFCLO(badid)) != 0) {
            /* problems closing badpixel frame */
            return(MAREMMA);
        }


        /* close the data frame */
        if ((status = SCFCLO(frameid)) != 0) {
            /* problems closing data frame */
            return(MAREMMA);
        }

    }

    free_ivector(fibres, 0,myflats->maxfibres-1);
    /* I read it all, exit */

    return NOERR;

}
