/*******************************************************************************
 * JMMC project ( http://www.jmmc.fr ) - Copyright (C) CNRS.
 ******************************************************************************/

/**
 * @file
 * Functions developped for Yorick interfacing 
 *
 * In Yorick, it is not possible to easily handle data which has been
 * dynamicaly allocated by an external C function, and which is just refered by
 * pointer. Yorick pointer points to a Yorick array of any data type or
 * dimensions, therefore it is not possible to display or use such data in
 * Yorick program. In order to counterpass this problem, the following
 * functions have been implemented to copy data from data structures allocated
 * by amdlib C function into data structure allocated by an external program;
 * yorick for instance which know in this case data type and dimensions. These
 * functions assume the destination data structure have been correctly
 * allocated. 
 */

/* 
 * System Headers
 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>


/* 
 * Local Headers
 */
#include "amdlib.h"
#include "amdlibProtected.h"
#include "amdlibYorick.h"

/*
 * Public functions definition
 */
/**
 * Copy region description part of amdlibREGION data structure. 
 *
 * @param srcRegions pointer to source data structure 
 * @param dstRegions pointer to destination data structure 
 * @param nbRegions number of regions 
 * @param errMsg error description message returned if function fails.
 *
 * @note 
 * This function is called first to get region dimensions in order to allocate
 * memory for region data before calling amdlibCopyRegionData() to copy data.
 *
 * @return
 * amdlibSUCCESS on successful completion. Otherwise amdlibFAILURE is returned.
 */
amdlibCOMPL_STAT amdlibCopyRegionInfo(amdlibREGION    *srcRegions, 
                                      amdlibREGION    *dstRegions, 
                                      int             nbRegions,
                                      amdlibERROR_MSG errMsg)
{
    int i, j;

    /* For each regions */
    for (i=0; i < nbRegions; i++)
    {
        /* Copy regions info */
        dstRegions[i].regionNumber = srcRegions[i].regionNumber;
        strcpy((char *)dstRegions[i].regionName, srcRegions[i].regionName);
        dstRegions[i].detectorNumber = srcRegions[i].detectorNumber;
        for (j=0; j<amdlibNB_TEL; j++)
        {
            dstRegions[i].ports[j] = srcRegions[i].ports[j];
        }
        dstRegions[i].correlation = srcRegions[i].correlation;
        dstRegions[i].corner[0] = srcRegions[i].corner[0];
        dstRegions[i].corner[1] = srcRegions[i].corner[1];
        dstRegions[i].gain = srcRegions[i].gain;
        dstRegions[i].crVal[0] = srcRegions[i].crVal[0];
        dstRegions[i].crVal[1] = srcRegions[i].crVal[1];
        dstRegions[i].crPix[0] = srcRegions[i].crPix[0];
        dstRegions[i].crPix[1] = srcRegions[i].crPix[1];
        strcpy((char *)dstRegions[i].cType[0], srcRegions[i].cType[0]);
        strcpy((char *)dstRegions[i].cType[1], srcRegions[i].cType[1]);
        dstRegions[i].cd[0][0] = srcRegions[i].cd[0][0];
        dstRegions[i].cd[0][1] = srcRegions[i].cd[0][1];
        dstRegions[i].cd[1][0] = srcRegions[i].cd[1][0];
        dstRegions[i].cd[1][1] = srcRegions[i].cd[1][1];
        dstRegions[i].dimAxis[0] = srcRegions[i].dimAxis[0];
        dstRegions[i].dimAxis[1] = srcRegions[i].dimAxis[1];
        dstRegions[i].dimAxis[2] = srcRegions[i].dimAxis[2];
    }
    return amdlibSUCCESS;
}

/**
 * Copy region data part of amdlibREGION data structure. 
 *
 * @param srcRegions pointer to source data structure 
 * @param dstRegions pointer to destination data structure 
 * @param nbRegions number of regions 
 * @param errMsg error description message returned if function fails.
 *
 * @return
 * amdlibSUCCESS on successful completion. Otherwise amdlibFAILURE is returned.
 */
amdlibCOMPL_STAT amdlibCopyRegionData(amdlibREGION    *srcRegions, 
                                      amdlibREGION    *dstRegions, 
                                      int             nbRegions,
                                      amdlibERROR_MSG errMsg)
{
    int i;
    int nbOfElements;
    /* For each regions */
    for (i=0; i < nbRegions; i++)
    {
        /* Compute the number of elements in the data array */
        nbOfElements = srcRegions[i].dimAxis[0] *
            srcRegions[i].dimAxis[1] *
            srcRegions[i].dimAxis[2];

        /* Check data pointer */
        if (srcRegions[i].data == NULL)
        {
            amdlibSetErrMsg("The (source) pointer to the data of region #%d "
                            "is invalid", i); 
            return amdlibFAILURE;
        }
        if (dstRegions[i].data == NULL)
        {
            amdlibSetErrMsg("The (destination) pointer to the data of "
                            "region #%d is invalid", i); 
            return amdlibFAILURE;
        }

        /* Copy the corresponding data */
        memcpy(dstRegions[i].data , srcRegions[i].data, 
               nbOfElements * sizeof(amdlibDOUBLE));
    }
    return amdlibSUCCESS;
}

/**
 * Copy amdlibSCIENCE_DATA data structure. 
 *
 * @param srcScienceData pointer to source data structure 
 * @param dstScienceData pointer to destination data structure 
 * @param errMsg error description message returned if function fails.
 *
 * @return
 * amdlibSUCCESS on successful completion. Otherwise amdlibFAILURE is returned.
 */
amdlibCOMPL_STAT amdlibCopyScienceData(amdlibSCIENCE_DATA *srcScienceData, 
                                       amdlibSCIENCE_DATA *dstScienceData, 
                                       amdlibERROR_MSG    errMsg)
{
    int frame, i;

    /* Update thisPtr field (not allocated if destination structure comes from
     * yorick) */
    if (dstScienceData->thisPtr != dstScienceData)
    {
        dstScienceData->thisPtr = dstScienceData;
    }
    
    /* Copy fixed size fields */
    dstScienceData->p2vmId = srcScienceData->p2vmId;

    /* Copy insCfg */
    for (i=0; i < srcScienceData->insCfg.nbKeywords; i++)
    {
        if (amdlibSetInsCfgKeyword(&(dstScienceData->insCfg),
                                   srcScienceData->insCfg.keywords[i].name,
                                   srcScienceData->insCfg.keywords[i].value,
                                   srcScienceData->insCfg.keywords[i].comment,
                                   errMsg) != amdlibSUCCESS)
        {
            return amdlibFAILURE;
        }
    }

    dstScienceData->expTime = srcScienceData->expTime;

    dstScienceData->nbCols = srcScienceData->nbCols;
    memcpy(dstScienceData->col, srcScienceData->col, 
           (amdlibMAX_NB_COLS-1) * sizeof(amdlibCOL_INFO));

    /* Copy fields allocated dynamically */
    memcpy(dstScienceData->timeTag,
           srcScienceData->timeTag,
           srcScienceData->nbFrames * sizeof(*(srcScienceData->timeTag)));

    dstScienceData->nbChannels = srcScienceData->nbChannels;
    memcpy(dstScienceData->channelNo,
           srcScienceData->channelNo,
           srcScienceData->nbChannels * sizeof(*(srcScienceData->channelNo)));

    dstScienceData->nbFrames = srcScienceData->nbFrames;

    for (frame = 0; frame < srcScienceData->nbFrames; frame++)
    {
        memcpy(dstScienceData->frame[frame].fluxRatio,
               srcScienceData->frame[frame].fluxRatio,
               amdlibNB_PHOTO_CHANNELS * 
               sizeof(*(dstScienceData->frame[frame].fluxRatio)));

        if (srcScienceData->frame[frame].intf != NULL)
        {
            memcpy(dstScienceData->frame[frame].intf, 
                   srcScienceData->frame[frame].intf,
                   srcScienceData->col[amdlibINTERF_CHANNEL].nbPixels * 
                   srcScienceData->nbChannels * sizeof(amdlibDOUBLE));
        }
        if (srcScienceData->frame[frame].sigma2Intf != NULL)
        {
            memcpy(dstScienceData->frame[frame].sigma2Intf, 
                   srcScienceData->frame[frame].sigma2Intf,
                   srcScienceData->col[amdlibINTERF_CHANNEL].nbPixels * 
                   srcScienceData->nbChannels * sizeof(amdlibDOUBLE));
        }
        if (srcScienceData->frame[frame].photo1 != NULL)
        {
            memcpy(dstScienceData->frame[frame].photo1, 
                   srcScienceData->frame[frame].photo1,
                   srcScienceData->nbChannels * sizeof(amdlibDOUBLE));
        }
        if (srcScienceData->frame[frame].photo2 != NULL)
        {
            memcpy(dstScienceData->frame[frame].photo2, 
                   srcScienceData->frame[frame].photo2,
                   srcScienceData->nbChannels * sizeof(amdlibDOUBLE));
        }
        if (srcScienceData->frame[frame].photo3 != NULL)
        {
            memcpy(dstScienceData->frame[frame].photo3, 
                   srcScienceData->frame[frame].photo3,
                   srcScienceData->nbChannels * sizeof(amdlibDOUBLE));
        }

        if (srcScienceData->frame[frame].sigma2Photo1 != NULL)
        {
            memcpy(dstScienceData->frame[frame].sigma2Photo1, 
                   srcScienceData->frame[frame].sigma2Photo1,
                   srcScienceData->nbChannels * sizeof(amdlibDOUBLE));
        }
        if (srcScienceData->frame[frame].sigma2Photo2 != NULL)
        {
            memcpy(dstScienceData->frame[frame].sigma2Photo2, 
                   srcScienceData->frame[frame].sigma2Photo2,
                   srcScienceData->nbChannels * sizeof(amdlibDOUBLE));
        }
        if (srcScienceData->frame[frame].sigma2Photo3 != NULL)
        {
            memcpy(dstScienceData->frame[frame].sigma2Photo3, 
                   srcScienceData->frame[frame].sigma2Photo3,
                   srcScienceData->nbChannels * sizeof(amdlibDOUBLE));
        }

        if (srcScienceData->badPixels != NULL)
        {
            memcpy (dstScienceData->badPixels, srcScienceData->badPixels, 
                    srcScienceData->col[amdlibINTERF_CHANNEL].nbPixels * 
                    srcScienceData->nbChannels * sizeof(char)); 
        }

        dstScienceData->frame[frame].snrPhoto1 = 
            srcScienceData->frame[frame].snrPhoto1;
        dstScienceData->frame[frame].snrPhoto2 = 
            srcScienceData->frame[frame].snrPhoto2;
        dstScienceData->frame[frame].snrPhoto3 = 
            srcScienceData->frame[frame].snrPhoto3;
        dstScienceData->frame[frame].integratedPhoto1 = 
            srcScienceData->frame[frame].integratedPhoto1;
        dstScienceData->frame[frame].integratedPhoto2 = 
            srcScienceData->frame[frame].integratedPhoto2;
        dstScienceData->frame[frame].integratedPhoto3 = 
            srcScienceData->frame[frame].integratedPhoto3;
    }

    return amdlibSUCCESS;
}

/**
 * Copy amdlibSELECTION data structure. 
 *
 * @param srcSelection pointer to source data structure 
 * @param dstSelection pointer to destination data structure 
 * @param errMsg error description message returned if function fails.
 *
 * @return
 * amdlibSUCCESS on successful completion. Otherwise amdlibFAILURE is returned.
 */
amdlibCOMPL_STAT amdlibCopySelection(amdlibSELECTION *srcSelection,
                                     amdlibSELECTION *dstSelection,
                                     amdlibERROR_MSG errMsg)
{
    int band, base;
    
    /* Copy fixed size fields */
    dstSelection->nbFrames = srcSelection->nbFrames;
    dstSelection->nbBases  = srcSelection->nbBases;
    
    /* For each band */
    for (band = 0; band < amdlibNB_BANDS; band++)
    {
        for (base = 0; base < srcSelection->nbBases; base++)
        {
            dstSelection->band[band].nbSelectedFrames[base] =
                srcSelection->band[band].nbSelectedFrames[base];
            dstSelection->band[band].firstSelectedFrame[base] =
                srcSelection->band[band].firstSelectedFrame[base];
        }
        dstSelection->band[band].nbFramesOkForClosure =
            srcSelection->band[band].nbFramesOkForClosure;

        /* Dynamical array */
        memcpy(dstSelection->band[band].isSelected, 
               srcSelection->band[band].isSelected, 
               sizeof(char) * srcSelection->nbFrames * srcSelection->nbBases);
        memcpy(dstSelection->band[band].frameOkForClosure, 
               srcSelection->band[band].frameOkForClosure, 
               sizeof(int) * srcSelection->nbFrames);
    }
    return amdlibSUCCESS;
}

/**
 * Copy amdlibOI_ARRAY data structure. 
 *
 * @param srcOiArray pointer to source data structure 
 * @param dstOiArray pointer to destination data structure 
 * @param errMsg error description message returned if function fails.
 *
 * @return
 * amdlibSUCCESS on successful completion. Otherwise amdlibFAILURE is returned.
 */
amdlibCOMPL_STAT amdlibCopyOiArray(amdlibOI_ARRAY  *srcOiArray,
                                   amdlibOI_ARRAY  *dstOiArray,
                                   amdlibERROR_MSG errMsg)
{
    int s, i;
    
    /* Update thisPtr field (not allocated if destination structure comes from
     * yorick) */
    if (dstOiArray->thisPtr != dstOiArray)
    {
        dstOiArray->thisPtr = dstOiArray;
    }

    /* Copy fixed size fields */
    dstOiArray->nbStations = srcOiArray->nbStations;
    strcpy(dstOiArray->arrayName, srcOiArray->arrayName);
    strcpy(dstOiArray->coordinateFrame, srcOiArray->coordinateFrame);
    for (i=0; i < 3; i++)
    {
        dstOiArray->arrayCenterCoordinates[i] = 
            srcOiArray->arrayCenterCoordinates[i];
    }
    
    /* Copy fields allocated dynamically */
    for (s=0; s < dstOiArray->nbStations; s++)
    {
        strcpy(dstOiArray->element[s].telescopeName, 
               srcOiArray->element[s].telescopeName);
        strcpy(dstOiArray->element[s].stationName, 
               srcOiArray->element[s].stationName);
        dstOiArray->element[s].stationIndex = 
            srcOiArray->element[s].stationIndex;
        dstOiArray->element[s].elementDiameter = 
            srcOiArray->element[s].elementDiameter;
        for (i=0; i < 3; i++)
        {
            dstOiArray->element[s].stationCoordinates[i] = 
                srcOiArray->element[s].stationCoordinates[i];
        }
    }
    
    return amdlibSUCCESS;
}

/**
 * Copy amdlibOI_TARGET data structure. 
 *
 * @param srcOiTarget pointer to source data structure 
 * @param dstOiTarget pointer to destination data structure 
 * @param errMsg error description message returned if function fails.
 *
 * @return
 * amdlibSUCCESS on successful completion. Otherwise amdlibFAILURE is returned.
 */
amdlibCOMPL_STAT amdlibCopyOiTarget(amdlibOI_TARGET *srcOiTarget,
                                    amdlibOI_TARGET *dstOiTarget,
                                    amdlibERROR_MSG errMsg)
{
    int t;
    
    /* Update thisPtr field (not allocated if destination structure comes from
     * yorick) */
    if (dstOiTarget->thisPtr != dstOiTarget)
    {
        dstOiTarget->thisPtr = dstOiTarget;
    }

    /* Copy fixed size fields */
    dstOiTarget->nbTargets = srcOiTarget->nbTargets;
    
    /* Copy fields allocated dynamically */
    for (t=0; t < dstOiTarget->nbTargets; t++)
    {
        strcpy(dstOiTarget->element[t].targetName, 
               srcOiTarget->element[t].targetName);
        strcpy(dstOiTarget->element[t].velTyp, srcOiTarget->element[t].velTyp);
        strcpy(dstOiTarget->element[t].velDef, srcOiTarget->element[t].velDef);
        strcpy(dstOiTarget->element[t].specTyp, 
               srcOiTarget->element[t].specTyp);

        dstOiTarget->element[t].targetId = srcOiTarget->element[t].targetId;
        dstOiTarget->element[t].equinox = srcOiTarget->element[t].equinox;
        dstOiTarget->element[t].raEp0 = srcOiTarget->element[t].raEp0;
        dstOiTarget->element[t].decEp0 = srcOiTarget->element[t].decEp0;
        dstOiTarget->element[t].raErr = srcOiTarget->element[t].raErr;
        dstOiTarget->element[t].decErr = srcOiTarget->element[t].decErr;
        dstOiTarget->element[t].sysVel = srcOiTarget->element[t].sysVel;
        dstOiTarget->element[t].pmRa = srcOiTarget->element[t].pmRa;
        dstOiTarget->element[t].pmDec = srcOiTarget->element[t].pmDec;
        dstOiTarget->element[t].pmRaErr = srcOiTarget->element[t].pmRaErr;
        dstOiTarget->element[t].pmDecErr = srcOiTarget->element[t].pmDecErr;
        dstOiTarget->element[t].parallax = srcOiTarget->element[t].parallax;
        dstOiTarget->element[t].paraErr = srcOiTarget->element[t].paraErr;
    }
    
    return amdlibSUCCESS;
}

/**
 * Copy amdlibPHOTOMETRY data structure. 
 *
 * @param srcPhotometry pointer to source data structure 
 * @param dstPhotometry pointer to destination data structure 
 * @param errMsg error description message returned if function fails.
 *
 * @return
 * amdlibSUCCESS on successful completion. Otherwise amdlibFAILURE is returned.
 */
amdlibCOMPL_STAT amdlibCopyPhotometry(amdlibPHOTOMETRY *srcPhotometry, 
                                      amdlibPHOTOMETRY *dstPhotometry, 
                                      amdlibERROR_MSG   errMsg)
{
    int entry;

    /* Update thisPtr field (not allocated if destination structure comes from
     * yorick) */
    if (dstPhotometry->thisPtr != dstPhotometry)
    {
        dstPhotometry->thisPtr = dstPhotometry;
    }
        
    /* Copy fixed size fields */
    dstPhotometry->nbFrames = srcPhotometry->nbFrames;
    dstPhotometry->nbBases = srcPhotometry->nbBases;
    dstPhotometry->nbWlen = srcPhotometry->nbWlen;

    /* Copy fields allocated dynamically */
    for (entry=0; entry<dstPhotometry->nbFrames*srcPhotometry->nbBases; entry++)
    {
        memcpy(dstPhotometry->table[entry].fluxSumPiPj,
               srcPhotometry->table[entry].fluxSumPiPj, 
               srcPhotometry->nbWlen * sizeof(double));
        memcpy(dstPhotometry->table[entry].sigma2FluxSumPiPj,
               srcPhotometry->table[entry].sigma2FluxSumPiPj, 
               srcPhotometry->nbWlen * sizeof(double));

        memcpy(dstPhotometry->table[entry].fluxRatPiPj, 
               srcPhotometry->table[entry].fluxRatPiPj, 
               srcPhotometry->nbWlen * sizeof(double));
        memcpy(dstPhotometry->table[entry].sigma2FluxRatPiPj,
               srcPhotometry->table[entry].sigma2FluxRatPiPj, 
               srcPhotometry->nbWlen * sizeof(double));

        memcpy(dstPhotometry->table[entry].PiMultPj, 
               srcPhotometry->table[entry].PiMultPj, 
               srcPhotometry->nbWlen * sizeof(double));
    }
    return amdlibSUCCESS;
}

/**
 * Copy amdlibVIS data structure. 
 *
 * @param srcVis pointer to source data structure 
 * @param dstVis pointer to destination data structure 
 * @param errMsg error description message returned if function fails.
 *
 * @return
 * amdlibSUCCESS on successful completion. Otherwise amdlibFAILURE is returned.
 */
amdlibCOMPL_STAT amdlibCopyVis(amdlibVIS *srcVis, 
                               amdlibVIS *dstVis, 
                               amdlibERROR_MSG   errMsg)
{
    int entry;

    /* Update thisPtr field (not allocated if destination structure comes from
     * yorick) */
    if (dstVis->thisPtr != dstVis)
    {
        dstVis->thisPtr = dstVis;
    }
    /* Copy fixed size fields */
    dstVis->nbFrames = srcVis->nbFrames;
    dstVis->nbBases = srcVis->nbBases;
    dstVis->nbWlen = srcVis->nbWlen;

    /* Copy fields allocated dynamically */
    for (entry=0; entry<dstVis->nbFrames*srcVis->nbBases; entry++)
    {
        dstVis->table[entry].targetId = srcVis->table[entry].targetId;

        dstVis->table[entry].time = srcVis->table[entry].time;

        dstVis->table[entry].dateObsMJD = srcVis->table[entry].dateObsMJD;

        dstVis->table[entry].expTime = srcVis->table[entry].expTime;

        dstVis->table[entry].uCoord = srcVis->table[entry].uCoord;

        dstVis->table[entry].vCoord = srcVis->table[entry].vCoord;

        dstVis->table[entry].stationIndex[0] =
            srcVis->table[entry].stationIndex[0];

        dstVis->table[entry].stationIndex[1] =
            srcVis->table[entry].stationIndex[1];

        memcpy(dstVis->table[entry].bandFlag, srcVis->table[entry].bandFlag,
               amdlibNB_BANDS * sizeof(amdlibBOOLEAN));
        
        memcpy(dstVis->table[entry].frgContrastSnrArray, 
               srcVis->table[entry].frgContrastSnrArray,
               amdlibNB_BANDS * sizeof(double));
        dstVis->table[entry].frgContrastSnr = 
		    srcVis->table[entry].frgContrastSnr;

        memcpy(dstVis->table[entry].flag, srcVis->table[entry].flag,
               srcVis->nbWlen * sizeof(amdlibBOOLEAN));

        memcpy(dstVis->table[entry].vis, srcVis->table[entry].vis, 
               srcVis->nbWlen * sizeof(amdlibCOMPLEX));

        memcpy(dstVis->table[entry].sigma2Vis, srcVis->table[entry].sigma2Vis, 
               srcVis->nbWlen * sizeof(amdlibCOMPLEX));

        memcpy(dstVis->table[entry].visCovRI, srcVis->table[entry].visCovRI, 
               srcVis->nbWlen * sizeof(double));

        memcpy(dstVis->table[entry].diffVisAmp, srcVis->table[entry].diffVisAmp,
               srcVis->nbWlen * sizeof(double));

        memcpy(dstVis->table[entry].diffVisAmpErr,
               srcVis->table[entry].diffVisAmpErr,
               srcVis->nbWlen * sizeof(double));

        memcpy(dstVis->table[entry].diffVisPhi, srcVis->table[entry].diffVisPhi,
               srcVis->nbWlen * sizeof(double));

        memcpy(dstVis->table[entry].diffVisPhiErr,
               srcVis->table[entry].diffVisPhiErr, 
               srcVis->nbWlen * sizeof(double));
    }
    return amdlibSUCCESS;
}

/**
 * Copy amdlibVIS2 data structure. 
 *
 * @param srcVis2 pointer to source data structure 
 * @param dstVis2 pointer to destination data structure 
 * @param errMsg error description message returned if function fails.
 *
 * @return
 * amdlibSUCCESS on successful completion. Otherwise amdlibFAILURE is returned.
 */
amdlibCOMPL_STAT amdlibCopyVis2(amdlibVIS2 *srcVis2, 
                                amdlibVIS2 *dstVis2, 
                                amdlibERROR_MSG   errMsg)
{
    int entry;

    /* Update thisPtr field (not allocated if destination structure comes from
     * yorick) */
    if (dstVis2->thisPtr != dstVis2)
    {
        dstVis2->thisPtr = dstVis2;
    }
    
    /* Copy fixed size fields */
    dstVis2->nbFrames = srcVis2->nbFrames;
    dstVis2->nbBases = srcVis2->nbBases;
    dstVis2->nbWlen = srcVis2->nbWlen;
    dstVis2->vis12 = srcVis2->vis12;
    dstVis2->vis23 = srcVis2->vis23;
    dstVis2->vis31 = srcVis2->vis31;
    dstVis2->sigmaVis12 = srcVis2->sigmaVis12;
    dstVis2->sigmaVis23 = srcVis2->sigmaVis23;
    dstVis2->sigmaVis31 = srcVis2->sigmaVis31;

    /* Copy fields allocated dynamically */
    for (entry=0; entry<dstVis2->nbFrames*srcVis2->nbBases; entry++)
    {
        dstVis2->table[entry].targetId = srcVis2->table[entry].targetId;
        dstVis2->table[entry].time = srcVis2->table[entry].time;
        dstVis2->table[entry].dateObsMJD = srcVis2->table[entry].dateObsMJD;
        dstVis2->table[entry].expTime = srcVis2->table[entry].expTime;
        dstVis2->table[entry].uCoord = srcVis2->table[entry].uCoord;
        dstVis2->table[entry].vCoord = srcVis2->table[entry].vCoord;
        dstVis2->table[entry].stationIndex[0] =
            srcVis2->table[entry].stationIndex[0];
        dstVis2->table[entry].stationIndex[1] =
            srcVis2->table[entry].stationIndex[1];
        memcpy(dstVis2->table[entry].vis2, srcVis2->table[entry].vis2, 
               srcVis2->nbWlen * sizeof(double));
        memcpy(dstVis2->table[entry].vis2Error, 
               srcVis2->table[entry].vis2Error, 
               srcVis2->nbWlen * sizeof(double));
        memcpy(dstVis2->table[entry].flag, srcVis2->table[entry].flag,
               srcVis2->nbWlen * sizeof(amdlibBOOLEAN));
    }
    return amdlibSUCCESS;
}

/**
 * Copy amdlibVIS3 data structure. 
 *
 * @param srcVis3 pointer to source data structure 
 * @param dstVis3 pointer to destination data structure 
 * @param errMsg error description message returned if function fails.
 *
 * @return
 * amdlibSUCCESS on successful completion. Otherwise amdlibFAILURE is returned.
 */
amdlibCOMPL_STAT amdlibCopyVis3(amdlibVIS3 *srcVis3, 
                                amdlibVIS3 *dstVis3, 
                                amdlibERROR_MSG   errMsg)
{
    int entry;

    /* Update thisPtr field (not allocated if destination structure comes from
     * yorick) */
    if (dstVis3->thisPtr != dstVis3)
    {
        dstVis3->thisPtr = dstVis3;
    }
    
    /* Copy fixed size fields */
    dstVis3->nbFrames = srcVis3->nbFrames;
    dstVis3->nbClosures = srcVis3->nbClosures;
    dstVis3->nbWlen = srcVis3->nbWlen;
    dstVis3->averageClosure = srcVis3->averageClosure;
    dstVis3->averageClosureError = srcVis3->averageClosureError;

    /* Copy fields allocated dynamically */
    for (entry=0; entry<dstVis3->nbFrames*dstVis3->nbClosures; entry++)
    {
        dstVis3->table[entry].targetId = srcVis3->table[entry].targetId;
        dstVis3->table[entry].time = srcVis3->table[entry].time;
        dstVis3->table[entry].dateObsMJD = srcVis3->table[entry].dateObsMJD;
        dstVis3->table[entry].expTime = srcVis3->table[entry].expTime;
        dstVis3->table[entry].u1Coord = srcVis3->table[entry].u1Coord;
        dstVis3->table[entry].v1Coord = srcVis3->table[entry].v1Coord;
        dstVis3->table[entry].u2Coord = srcVis3->table[entry].u2Coord;
        dstVis3->table[entry].v2Coord = srcVis3->table[entry].v2Coord;
        dstVis3->table[entry].stationIndex[0] =
            srcVis3->table[entry].stationIndex[0];
        dstVis3->table[entry].stationIndex[1] =
            srcVis3->table[entry].stationIndex[1];
        dstVis3->table[entry].stationIndex[2] =
            srcVis3->table[entry].stationIndex[2];
        memcpy(dstVis3->table[entry].vis3Amplitude, 
               srcVis3->table[entry].vis3Amplitude, 
               srcVis3->nbWlen * sizeof(double));
        memcpy(dstVis3->table[entry].vis3AmplitudeError,
               srcVis3->table[entry].vis3AmplitudeError, 
               srcVis3->nbWlen * sizeof(double));
        memcpy(dstVis3->table[entry].vis3Phi, srcVis3->table[entry].vis3Phi, 
               srcVis3->nbWlen * sizeof(double));
        memcpy(dstVis3->table[entry].vis3PhiError,
               srcVis3->table[entry].vis3PhiError, 
               srcVis3->nbWlen * sizeof(double));
        memcpy(dstVis3->table[entry].flag, srcVis3->table[entry].flag,
               srcVis3->nbWlen * sizeof(amdlibBOOLEAN));
    }
    return amdlibSUCCESS;
}

/**
 * Copy amdlibPISTON data structure. 
 *
 * @param srcOpd pointer to source data structure 
 * @param dstOpd pointer to destination data structure 
 * @param errMsg error description message returned if function fails.
 *
 * @return
 * amdlibSUCCESS on successful completion. Otherwise amdlibFAILURE is returned.
 */
amdlibCOMPL_STAT amdlibCopyPiston(amdlibPISTON *srcOpd, 
                                  amdlibPISTON *dstOpd, 
                                  amdlibERROR_MSG   errMsg)
{
    int band;
    
    /* Update thisPtr field (not allocated if destination structure comes from
     * yorick) */
    if (dstOpd->thisPtr != dstOpd)
    {
        dstOpd->thisPtr = dstOpd;
    }
    
    /* Copy fixed size fields */
    dstOpd->nbFrames = srcOpd->nbFrames;
    dstOpd->nbBases = srcOpd->nbBases;
    memcpy(dstOpd->bandFlag, srcOpd->bandFlag, 
           amdlibNB_BANDS * sizeof(amdlibBOOLEAN));

    /* Copy fields allocated dynamically */
    for (band=amdlibJ_BAND; band <= amdlibK_BAND; band++)
    {
        memcpy(dstOpd->pistonOPDArray[band], 
               srcOpd->pistonOPDArray[band], 
               srcOpd->nbFrames * srcOpd->nbBases * sizeof(amdlibDOUBLE));
        memcpy(dstOpd->sigmaPistonArray[band], 
               srcOpd->sigmaPistonArray[band], 
               srcOpd->nbFrames * srcOpd->nbBases * sizeof(amdlibDOUBLE));
    }
    memcpy(dstOpd->pistonOPD, srcOpd->pistonOPD, 
           srcOpd->nbFrames * srcOpd->nbBases * sizeof(amdlibDOUBLE));
    memcpy(dstOpd->sigmaPiston, srcOpd->sigmaPiston, 
           srcOpd->nbFrames * srcOpd->nbBases * sizeof(amdlibDOUBLE));    
    
    return amdlibSUCCESS;
}

/**
 * Copy amdlibWAVELENGTH data structure. 
 *
 * @param srcWlen pointer to source data structure 
 * @param dstWlen pointer to destination data structure 
 * @param errMsg error description message returned if function fails.
 *
 * @return
 * amdlibSUCCESS on successful completion. Otherwise amdlibFAILURE is returned.
 */
amdlibCOMPL_STAT amdlibCopyWavelength(amdlibWAVELENGTH *srcWlen, 
                                      amdlibWAVELENGTH *dstWlen, 
                                      amdlibERROR_MSG   errMsg)
{
    /* Copy fixed size fields */
    dstWlen->nbWlen = srcWlen->nbWlen;

    /* Update thisPtr field (not allocated if destination structure comes from
     * yorick) */
    if (dstWlen->thisPtr != dstWlen)
    {
        dstWlen->thisPtr = dstWlen;
    }
    /* Copy fields allocated dynamically */
    memcpy(dstWlen->wlen, srcWlen->wlen, 
           srcWlen->nbWlen * sizeof(amdlibDOUBLE));
    memcpy(dstWlen->bandwidth, srcWlen->bandwidth, 
           srcWlen->nbWlen * sizeof(amdlibDOUBLE));
    return amdlibSUCCESS;
}
/**
 * Copy amdlibSPECTRUM data structure. 
 *
 * @param srcSpectrum pointer to source data structure 
 * @param dstSpectrum pointer to destination data structure 
 * @param errMsg error description message returned if function fails.
 *
 * @return
 * amdlibSUCCESS on successful completion. Otherwise amdlibFAILURE is returned.
 */
amdlibCOMPL_STAT amdlibCopySpectrum(amdlibSPECTRUM  *srcSpectrum, 
                                    amdlibSPECTRUM  *dstSpectrum, 
                                    amdlibERROR_MSG errMsg)
{
    int entry;

    /* Update thisPtr field (not allocated if destination structure comes from
     * yorick) */
    if (dstSpectrum->thisPtr != dstSpectrum)
    {
        dstSpectrum->thisPtr = dstSpectrum;
    }
        
    /* Copy fixed size fields */
    dstSpectrum->nbTels = srcSpectrum->nbTels;
    dstSpectrum->nbWlen = srcSpectrum->nbWlen;

    /* Copy fields allocated dynamically */
    for (entry=0; entry < dstSpectrum->nbTels; entry++)
    {
        memcpy(dstSpectrum->spec[entry],
               srcSpectrum->spec[entry], 
               srcSpectrum->nbWlen * sizeof(double));
        memcpy(dstSpectrum->specErr[entry],
               srcSpectrum->specErr[entry], 
               srcSpectrum->nbWlen * sizeof(double));
    }
    return amdlibSUCCESS;
}

/**
 * Copy amdlibBAD_PIXEL_MAP data structure. 
 *
 * @param dstBadPixel pointer to destination data structure 
 * @param errMsg error description message returned if function fails.
 *
 * @return
 * amdlibSUCCESS on successful completion. Otherwise amdlibFAILURE is returned.
 */
amdlibCOMPL_STAT amdlibCopyBadPixelMap(amdlibBAD_PIXEL_MAP *dstBadPixel, 
                                       amdlibERROR_MSG   errMsg)
{
    /* Get current bad pixel map */
    amdlibBAD_PIXEL_MAP *srcBadPixel;
    srcBadPixel = amdlibGetBadPixelMap();

    /* Copy it into destination structure */
    dstBadPixel->mapIsInitialized = srcBadPixel->mapIsInitialized;
    memcpy(dstBadPixel->data, srcBadPixel->data, 
           amdlibDET_SIZE_Y * amdlibDET_SIZE_X * sizeof(amdlibDOUBLE));

    return amdlibSUCCESS;
}

/**
 * Copy amdlibFLAT_FIELD_MAP data structure. 
 *
 * @param dstFlatField pointer to destination data structure 
 * @param errMsg error description message returned if function fails.
 *
 * @return
 * amdlibSUCCESS on successful completion. Otherwise amdlibFAILURE is returned.
 */
amdlibCOMPL_STAT amdlibCopyFlatFieldMap(amdlibFLAT_FIELD_MAP *dstFlatField, 
                                        amdlibERROR_MSG   errMsg)
{
    /* Get current bad pixel map */
    amdlibFLAT_FIELD_MAP *srcFlatField;
    srcFlatField = amdlibGetFlatFieldMap();

    /* Copy it into destination structure */
    dstFlatField->mapIsInitialized = srcFlatField->mapIsInitialized;
    memcpy(dstFlatField->data, srcFlatField->data, 
           amdlibDET_SIZE_Y * amdlibDET_SIZE_X * sizeof(amdlibDOUBLE));
    return amdlibSUCCESS;
}


/*___oOo___*/
