Skip to content
seqIDataMgr.cpp 109 KiB
Newer Older
/*
 * seqIDataMgr.cpp
 *
 *  Created on: Mar 18, 2022
 *      Author: Fulvio Laudisio
 */
#include <pthread.h>

#include <ctime>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>

#include "seqIDataMgr.hpp"

#include "base64.h" // from64tobits

SeqDataMgr * SeqDataMgr::m_pSeqDataMgr = NULL;

SeqDataMgr::SeqDataMgr(Ltcs::IifServiceWorkerInterfacePtr &_iif):
    sashaSave(IProperty::Switch, "sasha_save", "enable_save"),
    sashaObjName(IProperty::Text, "sasha", "OBJNAME"),
    sashaNumSeqs(IProperty::Number, "sasha", "num_seqs"),
    sashaSeqNum(IProperty::Number, "sasha", "seq_num"),
//    sashaNumCoadds(IProperty::Number, "sasha", "acquire"),
    sashaNumCoadds(IProperty::Number, "sasha", "num_coadds"),
    sashaNumDrops(IProperty::Number, "sasha", "num_drops"),
    sashaNumReads(IProperty::Number, "sasha", "num_reads"),
    sashaNumGroups(IProperty::Number, "sasha", "num_groups"),
    sashaNumResets(IProperty::Number, "sasha", "num_resets"),
    sashaReadout(IProperty::Text, "sasha", "def_readout_region_name"),
    sashaBlob(IProperty::Unknown, "sasha_save", "save_image"),
    sashaLargestFileNumber(IProperty::Number, "sasha_save", "largest_filenum"),
    sashaExposeProp(IProperty::Switch, "sasha", "start_acquire"),
    sharknirTemperatureA(IProperty::Unknown, "sharknir_temp", "sensor"),
    sharknirTemperatureB(IProperty::Unknown, "sharknir_temp", "sensor"),
sharknirws2's avatar
sharknirws2 committed
    sharknirPressure1(IProperty::Unknown, "sharknir_pres1", "sensor"),
    sashaStop(IProperty::Switch, "sasha", "stop"),
    sashaFrequencyMode(IProperty::Text, "sasha", "def_mode_name"),
    sashaEnableCont(IProperty::Switch, "sasha" , "enable_cont" )
{
    U6_LLOG(__FUNCTION__);
    // m_ptrIc = boost::shared_ptr<indiClient>(new indiClient(*_ptrIoService, m_ptrSharedQueue, "127.0.0.1", "7624"));
//    m_ptrIc2 = boost::shared_ptr<indiClient2>(new indiClient2(_ptrIoService, "193.206.241.72", "7624")); // TODO : UNHARDCODE sashaws IP and get it from obs_ctrl-ice.cfg
    // m_ptrIc2 = boost::shared_ptr<indiClient2>(new indiClient2(_ptrIoService, _callback_register, "127.0.0.1", "7624"));
//    D_LLOG("created pointer to indiClient2 object");

    m_iif = _iif;
    m_ExpectedBlobs = 0;
    SeqDataMgr::m_pSeqDataMgr = this;
    m_pGetMotorStatus = NULL;

//    sashaBlob.add(IElement("file"));


    m_sashaProps.insert(std::pair<std::string, IProperty & >("NDIT", sashaNumSeqs));
    m_sashaProps.insert(std::pair<std::string, IProperty & >("NDITINDEX", sashaSeqNum));
    m_sashaProps.insert(std::pair<std::string, IProperty & >("READOUT", sashaReadout));
    m_sashaProps.insert(std::pair<std::string, IProperty & >("SAVE", sashaSave));
    m_sashaProps.insert(std::pair<std::string, IProperty & >("OBJECTNAME", sashaObjName));
    m_sashaProps.insert(std::pair<std::string, IProperty & >("NCOADDS", sashaNumCoadds));
    m_sashaProps.insert(std::pair<std::string, IProperty & >("NDROPS", sashaNumDrops));
    m_sashaProps.insert(std::pair<std::string, IProperty & >("NGROUPS", sashaNumGroups));
    m_sashaProps.insert(std::pair<std::string, IProperty & >("NREADS", sashaNumReads));
    m_sashaProps.insert(std::pair<std::string, IProperty & >("NRESETS", sashaNumResets));
    m_sashaProps.insert(std::pair<std::string, IProperty & >("EXPOSE", sashaExposeProp));
    m_sashaProps.insert(std::pair<std::string, IProperty & >("STOP", sashaStop));
    m_sashaProps.insert(std::pair<std::string, IProperty & >("FREQUENCY", sashaFrequencyMode));
    m_sashaProps.insert(std::pair<std::string, IProperty & >("CONTINUOUS", sashaEnableCont));

    m_sashaProps.insert(std::pair<std::string, IProperty & >("LARGESTFILENUM", sashaLargestFileNumber));

    m_sashaProps.insert(std::pair<std::string, IProperty & >("SENSORTEMPA", sharknirTemperatureA));
    m_sashaProps.insert(std::pair<std::string, IProperty & >("SENSORTEMPB", sharknirTemperatureB));
sharknirws2's avatar
sharknirws2 committed
    m_sashaProps.insert(std::pair<std::string, IProperty & >("SENSORPRES1", sharknirPressure1));

    m_sashaPropsSet["NDIT"] = true;
    m_sashaPropsSet["NDITINDEX"] = true;
    m_sashaPropsSet["READOUT"] = true;
    m_sashaPropsSet["SAVE"] = true;
    m_sashaPropsSet["OBJECTNAME"] = true;
    m_sashaPropsSet["NCOADDS"] = true;
    m_sashaPropsSet["NDROPS"] = true;
    m_sashaPropsSet["NGROUPS"] = true;
    m_sashaPropsSet["NREADS"] = true;
    m_sashaPropsSet["NRESETS"] = true;
    m_sashaPropsSet["EXPOSE"] = true;
    m_sashaPropsSet["FREQUENCY"] = true;

    m_sashaTiming["Full_Image"] = 4.2783f;
    m_sashaTiming["Center"] = 2.6751f;
    m_sashaTiming["Bottom"] = 1.0719f;
    m_sashaTiming["Top"] = 1.0719f;
    m_sashaTiming["256x256"] = 0.2745f;
    m_sashaTiming["128x128"] = 0.0718f;
    m_sashaTiming["1000x1000"] = 4.0481;
    m_sashaTiming["coro_stripe"] = 0.1283;
    m_sashaTiming["PD_wollaston_stripe_small"] = 0.1701;
    m_sashaTiming["PD_wollaston_stripe_large"] = 0.2953;

    m_getFitsAbortFlag = 0;
    m_bReceivingFitsFile = false;

    m_curInstMode = "GEN";
    StartIndiClientThread();

    //Flags
    m_bFlagChanged = true;
    m_bSaveOnlyExposedFiles = true;
    m_bSaveIncomingBlob = false;

    m_instrumentHeader.init = true;
    updateInstrumentHeader();


    U8_LLOG("");
}


void SeqDataMgr::StartIndiClientThread()
{
    pthread_create(&m_indi_tid, NULL, indi_client_thread, this);
}


SeqDataMgr::~SeqDataMgr()
{
}


#define OCS_FRAME_TIME_FULLIMAGE    4.2783f
#define OCS_FRAME_TIME_CENTER       2.6751f
#define OCS_FRAME_TIME_BOTTOM       1.0719f
#define OCS_FRAME_TIME_TOP          1.0719f
#define OCS_FRAME_TIME_256X256      0.2745f
#define OCS_FRAME_TIME_128X128      0.0718f
#define OCS_FRAME_TIME_1000X1000    4.0481f
#define OCS_FRAME_TIME_COROSTRIPE   0.1283f
#define OCS_FRAME_TIME_WOLLASTONE   0.2953f
#define OCS_NUM_MAX_FRAMES 25
void set_ramp(float exp_time, float frame_time, int num_max_frames, int ncoadds, int &groups, int &reads, int &drops)
{
    float r = exp_time / (frame_time * ncoadds);
    float eff_frame_time = frame_time * ncoadds;
    if (r < num_max_frames)
    {
        groups = 1;
        reads = (int) r;
        if (r < 1.f)
            reads = 1;
        drops = 0;
    }
    else
    {
        groups = num_max_frames;
        reads = 1;
        float fpdrops = (exp_time - groups * eff_frame_time) / ((groups - 1) * eff_frame_time);
        int floor_drops = (int) fpdrops;
        float eff_exp_time = eff_frame_time * (groups * reads + (groups - 1) * floor_drops);
        float extra_time = eff_frame_time * (groups - 1);
        if (abs(exp_time - eff_exp_time) < abs(exp_time - (eff_exp_time + extra_time)))
        {
            drops = floor_drops;
        }
        else
        {
            drops = floor_drops + 1;
        }
    }
}


std::string get_current_wdir()
{
    char buff[FILENAME_MAX];
    getcwd(buff, FILENAME_MAX);
    std::string curr_work_dir(buff);
    return curr_work_dir;
}


float * get_modified_julian_day()
{
    time_t rawtime;
    time(&rawtime);
//    "rawtime = Numero di secondi dal 1 Gen 1970 00:00"
//    "MJD = Numero di giorni dalla mezzanotte del 17 Nov 1858"
    const int mjd_of_01011970 = 40587;
    double seconds = rawtime;
    static float result = mjd_of_01011970 + seconds/86400.;
    return &result;
}


int SeqDataMgr::setContext(const std::map<std::string, std::string> & _osContext)
    std::map<std::string, std::string>::const_iterator itContext;
    itContext = _osContext.find("CAL_FIBER_DEFOCUS_LAMP");
    if(itContext != _osContext.end())
    {
        if(itContext->second == "ON" || itContext->second == "OFF")
        {
            m_obContext.defocus_lamp = itContext->second;
            m_instrumentHeader.cal_fiber_defocus_lamp.status = m_obContext.defocus_lamp == "ON";
        }
        else
        {
            std::stringstream log_msg;
            log_msg << "Error : admitted values for " << itContext->first << " are \"ON\" or \"OFF\"";
            E_LLOG(log_msg.str());
            throw(std::runtime_error(log_msg.str()));
        }
    }
    else
    {
        m_obContext.defocus_lamp.clear();    
    }
    itContext = _osContext.find("CAL_FIBER_FOCUS_LAMP");
    if(itContext != _osContext.end())
    {
        if(itContext->second == "ON" || itContext->second == "OFF")
        {
            m_obContext.focus_lamp = itContext->second;
            m_instrumentHeader.cal_fiber_focus_lamp.status = m_obContext.focus_lamp == "ON";
        }
        else
        {
            std::stringstream log_msg;
            log_msg << "Error : admitted values for " << itContext->first << " are \"ON\" or \"OFF\"";
            E_LLOG(log_msg.str());
            throw(std::runtime_error(log_msg.str()));
        }
    }
    else
    {
        m_obContext.focus_lamp.clear();    
    }
    itContext = _osContext.find("OBSERVATION_BLOCK");
    if(itContext != _osContext.end())
    {
        m_obContext.observation_block = itContext->second;
    }
    else
    {
        m_obContext.observation_block.clear();    
    }
    itContext = _osContext.find("TEMPLATE_NAME");
    if(itContext != _osContext.end())
    {
        m_obContext.template_name = itContext->second;
    }
    else
    {
        m_obContext.template_name.clear();    
    }
    return 0;
}


int SeqDataMgr::sashaExpose(const std::map<std::string, std::string> & _dSashaExpose)
{
    U6_LLOG(__FUNCTION__ << " ~ DEPRECATED");
    Ice::Int status = EXIT_FAILURE;
#ifdef UNDEFINED
//  lbto::result res;
    lbto::DDstruct ddt;
    lbto::SeqDD dd;
    std::string ha = "";
//  double za;
    std::vector<std::string> vecFitsKey;
    std::vector<std::string> vecFitsComment;

    // AIRMASS (to be asked to TCS) Airmass
    ddt.DDname = "AirMass";
    dd.push_back(ddt);
    //vecFitsKey.push_back("AIRMASS");
    // HA  //  to HA = LST - RA
    ha = m_iif->getHourAngle();
//  status = datamgrPrintFITS("HA", ha, "hour angle at start of observation MJD-OBS", IceUtil::None, _c);
//  ZD (zenith distance)
//  za = 90 * 60 * 60 - m_iif->getAlt();
//  status = datamgrPrintFITS("ZD", su::convertTypeToString<double>(za), "zenith distance of LBT mount at MJD-OBS [deg]", IceUtil::None, _c);
    // MOONANGL
    // SUNANGL
    ddt.DDname = "ParAngle";
    dd.push_back(ddt);
    //m_mapFitsComments["PARANGLE"] = "Parallactic angle at start [deg]";
    ddt.DDname = "L_PosAngle";
    dd.push_back(ddt);
    //m_mapFitsComment["POSANGLE"] = "Telescope position angle [deg]";
    ddt.DDname = "L_RotAngle";
    dd.push_back(ddt);
    //m_mapFitsComment["ROTANGLE"] = "Telescope rotator angle [deg]";
    ddt.DDname = "L_RotMode";
    dd.push_back(ddt);
    //m_mapFitsComment["ROTASTAT"] = "Telescope rotator status";
    ddt.DDname = "L_M1X";
    dd.push_back(ddt);
    //m_mapFitsComment["M1-X"] = "X position of primary mirror [mm]";
    ddt.DDname = "L_M1Y";
    dd.push_back(ddt);
    //m_mapFitsComment["M1-Y"] = "Y position of primary mirror [mm]";
    ddt.DDname = "L_M1Z";
    dd.push_back(ddt);
    //m_mapFitsComment["M1-Z"] = "Z position of primary mirror [mm]";
    ddt.DDname = "L_M1RX";
    dd.push_back(ddt);
    //m_mapFitsComment["M1-RX"] = "Tilt of primary across X axis [arcsecs]";
    ddt.DDname = "L_M1RY";
    dd.push_back(ddt);
    //m_mapFitsComment["M1-RY"] = "Tilt of primary across Y axis [arcsecs]";
    ddt.DDname = "L_M1RZ";
    dd.push_back(ddt);
    //m_mapFitsComment["M1-RZ"] = "Tilt of primary across Z axis [arcsecs]";
    ddt.DDname = "L_M2X";
    dd.push_back(ddt);
    //m_mapFitsComment["M2-X"] = "X position of secondary mirror [mm]";
    ddt.DDname = "L_M2Y";
    dd.push_back(ddt);
    //m_mapFitsComment["M2-Y"] = "Y position of secondary mirror [mm]";
    ddt.DDname = "L_M2Z";
    dd.push_back(ddt);
    //m_mapFitsComment["M2-Z"] = "Z position of secondary mirror [mm]";
    ddt.DDname = "L_M2RX";
    dd.push_back(ddt);
    //m_mapFitsComment["M2-RX"] = "Tilt of primary across X axis [arcsecs]";
    ddt.DDname = "L_M2RY";
    dd.push_back(ddt);
    //m_mapFitsComment["M2-RY"] = "Tilt of primary across Y axis [arcsecs]";
    ddt.DDname = "L_M2RZ";
    dd.push_back(ddt);
    //m_mapFitsComment["M2-RZ"] = "Tilt of primary across Z axis [arcsecs]";
    //res = m_iif->iifGetParameter(dd);
//   if (res.rescode == EXIT_SUCCESS)
//   {
//       for (unsigned int i = 1; i<res.resmsg.size(); i++)
//       {
//           status = datamgrPrintFITS(//vecFitsKey[i-1], res.resmsg[i], vecFitsComment[i-1], IceUtil::None, _c);
//       }
//   }
#endif
    U8_LLOG(__FUNCTION__ << " exiting");
    return status;
}


int SeqDataMgr::SetFitsValues(fitsfile *fptr)
{
sharknirws2's avatar
sharknirws2 committed
    U6_LLOG(__FUNCTION__);
sharknirws2's avatar
sharknirws2 committed
    /* here keywords should be added to SHINS FITS file header.
       Copy from ICD document and dtype from
       https://heasarc.gsfc.nasa.gov/docs/software/fitsio/c/c_user/node127.html */
sharknirws2's avatar
sharknirws2 committed
    int FitStatus = 0;

    char TBD[] = "TBD";
    char * strValue = TBD;
    int intValue = 0;
    float floatValue = 0.f;
    float floatValue2 = 1.f;
    bool boolValue = true;

    double lat_d = +32.701309;
    double lon_d = -109.889064;
    int elevatio = 3221;

    char time_string[24];
    time_t rawtime;
    time(&rawtime);
    strftime(time_string, 24, "%Y-%m-%dT%H:%M:%S.000", localtime(&rawtime));
    float bzero = 32768.f;
    float bscale = 1.f;

    fits_write_comment(fptr,      "Original MACIE file keys ---------------------------------------------", &FitStatus);
    fits_write_key(fptr, TFLOAT,  "BZERO    ", &bzero, "offset data range to that of unsigned short", &FitStatus);
    fits_write_key(fptr, TFLOAT,  "BSCALE   ", &bscale, "default scaling factor", &FitStatus);
    fits_write_key(fptr, TSTRING, "CAMERA   ", TBD, "Instrument name", &FitStatus);
    fits_write_key(fptr, TFLOAT,  "CAPCOMP  ", &floatValue, "PreAmp Compensation capacitor (0-63 counts)", &FitStatus);
    fits_write_key(fptr, TSTRING, "DTEOBSM", time_string, "Date at end of observation CCYY-MM-DD (UTC)", &FitStatus);
    fits_write_key(fptr, TSTRING, "DETECTOM", TBD, "H1RG / H2RG / H4RG", &FitStatus);
    fits_write_key(fptr, TSTRING, "EXPMODE  ", TBD, "SLOW / FAST", &FitStatus);
    fits_write_key(fptr, TFLOAT,  "EXPTIMEM ", &floatValue, "Total Exposure Time, millisec", &FitStatus);
    fits_write_key(fptr, TSTRING, "FILENAME ", TBD, "File name", &FitStatus);
    fits_write_key(fptr, TFLOAT,  "FILTPOLE ", &floatValue, "PreAmp Low Pass filter (0-15 counts)", &FitStatus);
    fits_write_key(fptr, TFLOAT,  "FRAME    ", &floatValue, "One frame time, millisec", &FitStatus);
    fits_write_key(fptr, TFLOAT,  "GAINM    ", &floatValue, "ASIC Preamplifier Gain in db from -3 to 27 in s", &FitStatus);
    fits_write_key(fptr, TFLOAT,  "ITIMEM   ", &floatValue, "Integration tim, millisecs", &FitStatus);
    fits_write_key(fptr, TFLOAT,  "NCOADDSM ", &floatValue, "Num Coadds", &FitStatus);
    fits_write_key(fptr, TFLOAT,  "NDROPS   ", &floatValue, "Num of Drops per Ramp", &FitStatus);
    fits_write_key(fptr, TFLOAT,  "NGROUPS  ", &floatValue, "Num of Groups per Ramp", &FitStatus);
    fits_write_key(fptr, TFLOAT,  "NOUTPUTS ", &floatValue, "1,2,4,16,32 for H2G, Number of outputs used for", &FitStatus);
    fits_write_key(fptr, TFLOAT,  "NRAMPS   ", &floatValue, "Num of Ramps to cycle through", &FitStatus);
    fits_write_key(fptr, TFLOAT,  "NREADSM  ", &floatValue, "Num of Read frames in each Group of ramp", &FitStatus);
    fits_write_key(fptr, TFLOAT,  "NRESETS  ", &floatValue, "Num of Reset Frames at the beginning of Ramp", &FitStatus);
    fits_write_key(fptr, TSTRING, "OBJNAMEM ", &TBD, "Target name", &FitStatus);
    fits_write_key(fptr, TFLOAT,  "RAMPTIM  ", &floatValue, "Ramp time, millisecs", &FitStatus);
    fits_write_key(fptr, TSTRING, "SUBSECNM ", &TBD, "Readout region name", &FitStatus);
    fits_write_key(fptr, TSTRING, "SUBSECH  ", &TBD, "Readout region height, FITS", &FitStatus);
    fits_write_key(fptr, TSTRING, "SUBSECW  ", &TBD, "Readout region width, FITS", &FitStatus);
    fits_write_key(fptr, TSTRING, "SUBSECX1 ", &TBD, "Readout region X1, FITS", &FitStatus);
    fits_write_key(fptr, TSTRING, "SUBSECX2 ", &TBD, "Readout region X2, FITS", &FitStatus);
    fits_write_key(fptr, TSTRING, "SUBSECY1 ", &TBD, "Readout region Y1, FITS", &FitStatus);
    fits_write_key(fptr, TSTRING, "SUBSECY2 ", &TBD, "Readout region Y2, FITS", &FitStatus);
    fits_write_key(fptr, TSTRING, "SYSSWVER ", &TBD, "Software version number", &FitStatus);
    fits_write_key(fptr, TSTRING, "TIME-END ", &TBD, "Time at end of observation HH:MM:SS:UUU (UTC)", &FitStatus);
    fits_write_key(fptr, TSTRING, "TIME-OBS ", &TBD, "Time at start of observation HH:MM:SS:UUU (UTC)", &FitStatus);
    fits_write_key(fptr, TFLOAT,  "USEREXP  ", &floatValue, "Requested Exposure Time, millisec", &FitStatus);
    fits_write_comment(fptr,      "End MACIE file keys --------------------------------------------------", &FitStatus);

//    fits_write_history(fptr,      "History and comments will be continued over multiple keyword if longer than 70 characters", &FitStatus);
//    fits_write_key(fptr, TSTRING, "COMMENT  ", strValue, "-----------------", &FitStatus);
    fits_write_key(fptr, TSTRING, "TPLNAME  ", su::get_char_star(m_obContext.template_name), "Template Name", &FitStatus);
    fits_write_key(fptr, TSTRING, "OBID     ", su::get_char_star(m_obContext.observation_block), "Observation Block Identifier", &FitStatus);
    fits_write_key(fptr, TSTRING, "BUNIT    ", strValue, "Physical Unit of array values, should be ADU", &FitStatus);
    fits_write_key(fptr, TINT,    "BLANK    ", &intValue, "Value used for NULL pixels", &FitStatus);

    fits_write_key(fptr, TSTRING, "ORIGIN   ", (char *) "MGIO-LBT", "Observatory", &FitStatus);
    fits_write_key(fptr, TDOUBLE, "LATITUDE ", &lat_d, "North latitude of LBT (deg; +=North)", &FitStatus);
    fits_write_key(fptr, TDOUBLE, "LONGITUD ", &lon_d, "Longitude of LBT (deg; +=East)", &FitStatus);
    fits_write_key(fptr, TINT,    "ELEVATIO ", &elevatio, "Elevation of LBT above sea level (m)", &FitStatus);
    fits_write_key(fptr, TSTRING, "TELESCOP ", (char *) "LBT-SX", "Telescope used", &FitStatus);
    boolValue = false; // TODO
    fits_write_key(fptr, TLOGICAL,"MASTER   ", &boolValue, "Is telescope acting as master", &FitStatus);
    fits_write_key(fptr, TSTRING, "INSTRUME ", (char *) "SHARK-NIR", "Instrument used", &FitStatus);
sharknirws2's avatar
sharknirws2 committed
    // U1_LLOG("Getting preset result ...");
    // res = m_iif->iifPresetTelescopeGet();
    // U1_LLOG("Getting preset result done");
    // if (res.rescode != EXIT_SUCCESS)
    //   {
    //     errorMsg = "Unable to preset telescope";
    //     A_LLOG(errorMsg << " with messages:");
    //     for (int i=0; i<res.resmsg.size(); i++)
    //       {
    // E_LLOG(res.resmsg[i]);
    //       }
    //     std::runtime_error err(errorMsg);
    //     throw err;
    //   }

    fits_write_record(fptr, "        ------------------------------------------------------------------------", &FitStatus);
        fits_write_key(fptr, TSTRING, "OBJECT   ", strValue, "Observation title given by observer", &FitStatus);
        fits_write_key(fptr, TSTRING, "OBJNAME  ", strValue, "Standard (IAU) object name", &FitStatus);
        fits_write_key(fptr, TSTRING, "COMMENT  ", strValue, "Observer's comments", &FitStatus);
    fits_write_key(fptr, TSTRING, "IMAGETYP ", strValue, "See Table 17 in RD6", &FitStatus);
    fits_write_key(fptr, TFLOAT,  "EXPTIME  ", &floatValue, "Total integration time (seconds)", &FitStatus);
    fits_write_key(fptr, TFLOAT,  "DIT      ", &floatValue, "Detector Integration Time", &FitStatus);
    fits_write_key(fptr, TFLOAT,  "NDIT     ", &floatValue, "Number of intergrations", &FitStatus);
        fits_write_key(fptr, TSTRING, "ORIGFILE ", strValue, "<instrume>.<yyyymmdd>.<nnnnn>.[science | calib | monit].fits orig filename at the tel (nnnnn is a 5 digit running num)", &FitStatus);
    fits_write_key(fptr, TSTRING, "CREATOR  ", (char *)"SHINS", "Software task that created this file", &FitStatus);
        fits_write_key(fptr, TINT,    "GRPNUM   ", &intValue, "Used to group related datafiles", &FitStatus);
        fits_write_key(fptr, TSTRING, "PARTNER  ", strValue, "Name of institute observing", &FitStatus);
    fits_write_key(fptr, TSTRING, "DATE     ", time_string, "'YYYY-MM-DDThh:mm:ss.sss' UTC date and time the file was written", &FitStatus);
    fits_write_key(fptr, TSTRING, "DATE-OBS ", time_string, "'YYYY-MM-DDThh:mm:ss.sss' UTC date and time of observation start", &FitStatus);
    fits_write_key(fptr, TSTRING, "UTC-OBS  ", strValue, "'hh:mm:ss.sss' UTC of observation start", &FitStatus);
    fits_write_key(fptr, TSTRING, "LST-OBS  ", strValue, "'hh:mm:ss.sss'  Local sidereal time at start of observation", &FitStatus);
    fits_write_key(fptr, TFLOAT,  "MJD-OBS  ", get_modified_julian_day(), "'nnnnn.nnnnn' Modified Julian Date at the start of the observation. 5 decimals for 1 second accuracy", &FitStatus);
        fits_write_key(fptr, TSTRING, "OBSERVER ", strValue, "Name of the observer", &FitStatus);
        fits_write_key(fptr, TSTRING, "PI-COI   ", strValue, "Name of PI", &FitStatus);
        fits_write_key(fptr, TSTRING, "PROPID   ", strValue, "Proposal identification      ", &FitStatus);

    int equinox = 2000;

    fits_write_key(fptr, TSTRING, "RADECSYS ", (char *) "FK5", " Reference system for the equatorial reference system", &FitStatus);
    fits_write_key(fptr, TINT,    "EQUINOX  ", &equinox, "Standard FK5 epoch for RA and DEC", &FitStatus);

//    U1_LLOG("getLST: " << m_iif->getLST());
//    U1_LLOG("getHourAngle: " << m_iif->getHourAngle());

    std::string tcs_dec = m_iif->getDEC();
    std::string tcs_ra = m_iif->getRA();
    float telalt = m_iif->getAlt();
    float telaz = m_iif->getAz();

    U9_LLOG("TCS RA = " << tcs_ra << " ; TCS DEC = " << tcs_dec << "; TCS_ALT = " << telalt << "; TCS_AZ = " << telaz);

    fits_write_key(fptr, TSTRING, "RA       ", su::get_char_star(tcs_ra), "'hh:mm:ss.ss' Right ascension (same as TELRA)", &FitStatus);
    fits_write_key(fptr, TSTRING, "DEC      ", su::get_char_star(tcs_dec), "'dd:mm:ss.s' Declination (same as DECRA)", &FitStatus);
        fits_write_key(fptr, TFLOAT,  "AIRMASS  ", &floatValue, "Airmass at start of observation MJD-OBS", &FitStatus);
    fits_write_key(fptr, TSTRING, "DATASUM  ", strValue, "Checksum of data section only", &FitStatus);
    fits_write_key(fptr, TSTRING, "CHECKSUM ", strValue, "ASCII 1's complement checksum", &FitStatus);
    fits_write_key(fptr, TSTRING, "CHECKVER ", (char *) "COMPLEMENT", "Checksum algorithm", &FitStatus);
        fits_write_key(fptr, TSTRING, "LBT_LOG  ", strValue, "Operations log entry", &FitStatus);

    fits_write_record(fptr, "        ------------------------------------------------------------------------", &FitStatus);
    fits_write_key(fptr, TSTRING, "PMODEL   ", strValue, "Pointing model in use", &FitStatus);
    fits_write_key(fptr, TSTRING, "OBJRADEC ", strValue, "RADEC system for OBJRA, OBJDEC", &FitStatus);
    fits_write_key(fptr, TSTRING, "OBJEQUIN ", strValue, "EQUINOX for OBJRA, OBJDEC", &FitStatus);
    fits_write_key(fptr, TSTRING, "OBJRA    ", strValue, "'hh:mm:ss' RA requested (from OB or catalog)", &FitStatus);
    fits_write_key(fptr, TSTRING, "OBJDEC   ", strValue, "'dd:mm:ss' DEC requested (from OB or catalog)", &FitStatus);
    fits_write_key(fptr, TFLOAT,  "OBJPMRA  ", &floatValue, "RA proper motion [mas]", &FitStatus);
    fits_write_key(fptr, TFLOAT,  "OBJPMDEC ", &floatValue, "DEC proper motion [mas]", &FitStatus);
    fits_write_key(fptr, TSTRING, "TELRA    ",  su::get_char_star(tcs_ra), "'hh:mm:ss.ss' RA at detector center at MJD-OBS", &FitStatus);
    fits_write_key(fptr, TSTRING, "TELDEC   ",  su::get_char_star(tcs_dec), "'dd:mm:ss.s' DEC at detector center at MJD-OBS", &FitStatus);
    fits_write_key(fptr, TFLOAT,  "TELALT   ", &telalt, "'dd.dd' LBT mount altitude at detector center at MJD-OBS", &FitStatus);
    fits_write_key(fptr, TFLOAT,  "TELAZ    ", &telaz, "'ddd.dd. LBT mount azimuth at detector center at MJD-OBS", &FitStatus);
    fits_write_key(fptr, TLOGICAL,"TRAKSTAT ", &boolValue, "Tracking status", &FitStatus);
    fits_write_key(fptr, TFLOAT,  "TELTKRA  ", &floatValue, "'0.0' Tracking rate from sidereal in RA [arcsec]", &FitStatus);
    fits_write_key(fptr, TFLOAT,  "TELTKDEC ", &floatValue, "'0.0' Tracking rate in DEC [arcsec]", &FitStatus);
    fits_write_key(fptr, TSTRING, "HA       ", strValue, "'+hh:mm:ss' hour angle at start of observation MJD-OBS", &FitStatus);
    fits_write_key(fptr, TFLOAT,  "ZD       ", &floatValue, "'dd.dd' zenith distance of LBT mount at MJD-OBS [deg]. Complement of TELALT", &FitStatus);
    fits_write_key(fptr, TFLOAT,  "MOONANGL ", &floatValue, "'ddd.ddd' Moon angle at start [deg]", &FitStatus);
    fits_write_key(fptr, TFLOAT,  "SUNANGLE ", &floatValue, "'ddd.ddd' Sun angle at start [deg]", &FitStatus);
    fits_write_key(fptr, TFLOAT,  "PARANGLE ", &floatValue, "'ddd.d' Parallactic angle at start [deg]", &FitStatus);
    fits_write_key(fptr, TFLOAT,  "POSANGLE ", &floatValue, "'ddd.d' Telescope position angle [deg]", &FitStatus);
    fits_write_key(fptr, TFLOAT,  "ROTANGLE ", &floatValue, "'dd.d' Telescope rotator angle [deg]", &FitStatus);
    fits_write_key(fptr, TSTRING, "ROTASTAT ", (char*) "OFF", "Rotator status. LBT rotator is always OFF when using SHARK-NIR", &FitStatus);


    /// TODO : INCLUDE TCS PRESET
    // TEL OBJECTNAME           Name of Target Object                       OBJECTNAME
    // TEL COORDINATE SYSTEM    Target Coordinate System                    CoordinateSystem
    // TEL OBJRA                Target RA                                   OBJRA
    // TEL OBJDEC               Target DEC                                  OBJDEC
    // TEL OBJQUIN              Target Coordinate System Equinox            OBJEQUIN
    // TEL PMRA                 Target RA Proper Motion                     PMRA
    // TEL PMDEC                Target DEC Proper Motion                    PMDEC
    // TEL AORA                 Adaptive Optics in RA                       AORA
    // TEL AODEC                Adaptive Optics in DEC                      AODEC
    // TEL PMAORA               Proper Motion of AO in RA                   PMAORA
    // TEL PMAODEC              Proper Motion of AO in DEC                  PMAODEC
    // TEL GSRA                 Guide Star RA                               GSRA
    // TEL GSDEC                Guide Star DEC                              GSDEC
    // TEL PMGSRA               Guide Star RA Proper Motion                 PMGSRA
    // TEL PMGSDEC              Guide Star DEC Proper Motion                PMGSDEC
    // TEL AOMode               Adaptive Optics Mode                        AOMODE
    // TEL OFFSET               Offset

// MISSING
//            "Epoch":"2022.5",
//            "Equinox": "j2000",
//            "BinocularFlag":"OFF",
//            "TelescopeMode": "ADAPTIVEACE_TRACK",
//            "TelescopeSide": "LEFT",

    fits_write_record(fptr, "        ------------------------------------------------------------------------", &FitStatus);
    fits_write_key(fptr, TFLOAT,  "M1-X     ", &floatValue, "X position of primary mirror [mm]", &FitStatus);
    fits_write_key(fptr, TFLOAT,  "M1-Y     ", &floatValue, "Y position of primary mirror [mm]", &FitStatus);
    fits_write_key(fptr, TFLOAT,  "M1-Z     ", &floatValue, "Focus of primary mirror [mm]", &FitStatus);
    fits_write_key(fptr, TFLOAT,  "M1-RX    ", &floatValue, "Tilt of primary across X axis [arcsecs]", &FitStatus);
    fits_write_key(fptr, TFLOAT,  "M1-RY    ", &floatValue, "Tilt of primary across X axis [arcsecs]", &FitStatus);
    fits_write_key(fptr, TFLOAT,  "M1-RZ    ", &floatValue, "Rotation of primary about Z axis [arcsecs]", &FitStatus);

    fits_write_key(fptr, TFLOAT,  "M2-X     ", &floatValue, "X position of secondary mirror [mm]", &FitStatus);
    fits_write_key(fptr, TFLOAT,  "M2-Y     ", &floatValue, "Y position of secondary mirror [mm]", &FitStatus);
    fits_write_key(fptr, TFLOAT,  "M2-Z     ", &floatValue, "Focus of secondary mirror [mm]", &FitStatus);
    fits_write_key(fptr, TFLOAT,  "M2-RX    ", &floatValue, "Tilt of secondary across X axis [arcsecs]", &FitStatus);
    fits_write_key(fptr, TFLOAT,  "M2-RY    ", &floatValue, "Tilt of secondary across X axis [arcsecs]", &FitStatus);
    fits_write_key(fptr, TFLOAT,  "M2-RZ    ", &floatValue, "Rotation of secondary about Z axis [arcsecs]", &FitStatus);

    fits_write_record(fptr, "        ------------------------------------------------------------------------", &FitStatus);

    STelescopeEnv tenv;
    getTelescopeEnv(tenv);
    fits_write_key(fptr, TFLOAT,   "DIMMSEEING",      &tenv.dimm_seeing,       "DIMM seeing, [arcsecs]", &FitStatus);
    fits_write_key(fptr, TFLOAT,   "DIMMMEANFLUX",    &floatValue,             "DIMM mean centroid flux", &FitStatus);
    fits_write_key(fptr, TLOGICAL, "LBTWEATHERALIVE", &tenv.lbt_weather_alive, "Weather Station Link State", &FitStatus);
    fits_write_key(fptr, TFLOAT,   "LBTPRESSURE",     &tenv.lbt_pressure,      "Ambient Pressure [hPa]", &FitStatus);
    fits_write_key(fptr, TFLOAT,   "LBTTEMP",         &tenv.lbt_temp,          "Ambient Temperature [deg C]", &FitStatus);
    fits_write_key(fptr, TFLOAT,   "LBTHUMIDITY",     &tenv.lbt_humidity,      "LBT Relative Humidity [percent]", &FitStatus);
    fits_write_key(fptr, TFLOAT,   "LBTDEWPOINT",     &tenv.lbt_dewpoint,      "LBT Dew Point [deg C]", &FitStatus);


    fits_write_record(fptr, "        ------------------------------------------------------------------------", &FitStatus);
    fits_write_key(fptr, TSTRING, "TELCONF  ", strValue,    "Telescope configuration", &FitStatus);
    fits_write_key(fptr, TFLOAT,  "FOCSCALE ", &floatValue, "Scale at focal plane [arcsec]", &FitStatus);
    fits_write_key(fptr, TSTRING, "INSMODE  ", strValue,    "Mode of use of instrument", &FitStatus);
    fits_write_key(fptr, TSTRING, "INSTHWV  ", strValue,    "Instrument hardware version", &FitStatus);
    fits_write_key(fptr, TSTRING, "INSTSWV  ", strValue,    "Instrument software version", &FitStatus);
    fits_write_key(fptr, TFLOAT,  "INSFOCUS ", &floatValue, "Instrument focus [mm]", &FitStatus);

    fits_write_key(fptr, TSTRING, "DETECTOR ", strValue, "Detector designation", &FitStatus);
    fits_write_key(fptr, TSTRING, "DETNAME  ", strValue, "Same as DETECTOR DETSIZE '[1:2048,1:2048]' Unbinned size of detector full array", &FitStatus);

    int nccds = 1;

    fits_write_key(fptr, TINT,    "NCCDS    ", &nccds, "Number of CCDs in the detector", &FitStatus);
    fits_write_key(fptr, TINT,    "NAMPS    ", &intValue, "Number of amplifiers in the detector", &FitStatus);
    fits_write_key(fptr, TINT,    "PIXSCAL1 ", &intValue, "Projected unbinned pixel scale along axis 1", &FitStatus);
    fits_write_key(fptr, TINT,    "PIXSCAL2 ", &intValue, "Projected unbinned pixel scale along axis 2", &FitStatus);

    int pixsize = 18;

    fits_write_key(fptr, TINT,    "PIXSIZE1 ", &pixsize,    "Unbinned det pix size [microns] along Axis 1", &FitStatus);
    fits_write_key(fptr, TINT,    "PIXSIZE2 ", &pixsize,    "Unbinned det pix size [microns] along Axis 2", &FitStatus);
    fits_write_key(fptr, TSTRING, "DETHWV   ", strValue,    "Detector hardware version", &FitStatus);
    fits_write_key(fptr, TSTRING, "DETSWV   ", strValue,    "Detector software version", &FitStatus);
    fits_write_key(fptr, TSTRING, "DETSTAT  ", strValue,    "Detector status", &FitStatus);
    fits_write_key(fptr, TSTRING, "DEWAR    ", strValue,    "Dewar identification", &FitStatus);
    fits_write_key(fptr, TSTRING, "DEWHWV   ", strValue,    "Dewar hardware version", &FitStatus);
    fits_write_key(fptr, TSTRING, "DEWSWV   ", strValue,    "Dewar software version", &FitStatus);
    fits_write_key(fptr, TSTRING, "DEWSTAT  ", strValue,    "Dewar status", &FitStatus);
    fits_write_key(fptr, TFLOAT,  "DEWTEM1  ", &floatValue, "Dewar temperature", &FitStatus);

    fits_write_record(fptr, "        ------------------------------------------------------------------------", &FitStatus);
    fits_write_key(fptr, TFLOAT,  "CCDTEM   ", &floatValue, "Detector temperature", &FitStatus);
    fits_write_key(fptr, TSTRING, "UDEWTEM  ", strValue,    "Units for Dewar temperatures", &FitStatus);
    fits_write_key(fptr, TSTRING, "UCCDTEM  ", strValue,    "Units for CCD temperature", &FitStatus);
    fits_write_key(fptr, TSTRING, "CCDNAME  ", strValue,    "Name of individual CCD (serial #)", &FitStatus);
    fits_write_key(fptr, TSTRING, "CCDID    ", strValue,    "Detector serial number (=ccdname)", &FitStatus);
    fits_write_key(fptr, TSTRING, "AMPNAME  ", strValue,    "Amplifier name", &FitStatus);
    fits_write_key(fptr, TSTRING, "CCDHW    ", strValue,    "Same as DETHWV if NCCDS = 1", &FitStatus);
    fits_write_key(fptr, TSTRING, "CCDSW    ", strValue,    "Same as DETSWV if NCCDS = 1", &FitStatus);
    fits_write_key(fptr, TSTRING, "CCDGAIN  ", strValue,    "CCD gain state", &FitStatus);
    fits_write_key(fptr, TFLOAT,  "GAIN     ", &floatValue, "Detector gain in e-/ADU", &FitStatus);
    fits_write_key(fptr, TFLOAT,  "RDNOISE  ", &floatValue, "Detector readout noise in e-", &FitStatus);
    fits_write_key(fptr, TINT,    "SATURATE ", &intValue,   "Saturation value in ADU", &FitStatus);
    fits_write_key(fptr, TSTRING, "BPM      ", strValue,    "Name of bad pixel mask", &FitStatus);
    fits_write_key(fptr, TSTRING, "CCDSIZE  ", strValue,    "'[x1:x2,y1:y2]' Same as DETSIZE", &FitStatus);
    fits_write_key(fptr, TSTRING, "CCDPSIZE ", strValue,    "'[x1:x2,y1:y2]' Same as CCDSIZE except for drift scanning", &FitStatus);
    fits_write_key(fptr, TINT,    "CCDSUM   ", &intValue,   "CCD on-chip summing (binning)", &FitStatus);
    fits_write_key(fptr, TSTRING, "AMPSIZE  ", strValue,    "'[x1:x2,y1:y2]' Unbinned amplifier readout size", &FitStatus);
    fits_write_key(fptr, TSTRING, "DATASEC  ", strValue,    "'[x1:x2,y1:y2]' Image data section", &FitStatus);
    fits_write_key(fptr, TSTRING, "CCDSEC   ", strValue,    "'[x1:x2,y1:y2]' Region of the CCD read", &FitStatus);
    fits_write_key(fptr, TSTRING, "DETSEC   ", strValue,    "'[x1:x2,y1:y2]' Detector section", &FitStatus);
    fits_write_key(fptr, TSTRING, "BIASSEC  ", strValue,    "'[x1:x2,y1:y2]' Bias section", &FitStatus);
    fits_write_key(fptr, TSTRING, "TRIMSEC  ", strValue,    "'[x1:x2,y1:y2]' Section of useful data", &FitStatus);
    fits_write_key(fptr, TSTRING, "AMPSEC   ", strValue,    "'[x1:x2,y1:y2]' Mapping of CCD section to amplifier coordinates", &FitStatus);
    fits_write_key(fptr, TINT,    "CCDNAMPS ", &intValue,   "Number of amplifiers to readout the CCD", &FitStatus);
    fits_write_key(fptr, TFLOAT,  "PREFLASH ", &floatValue, "CCD preflash time [ms]", &FitStatus);
    fits_write_key(fptr, TFLOAT,  "ITIME    ", &floatValue, "Exposure time[s] per coadd", &FitStatus);
    fits_write_key(fptr, TINT,    "NCOADDS  ", &intValue,   "Number of coadds (result is sum)", &FitStatus);
    fits_write_key(fptr, TINT,    "ACOAVGS  ", &intValue,   "Number of co-avgs (if individual exps are averaged and not summed –sum & NCOADDS preferred)", &FitStatus);
    fits_write_key(fptr, TFLOAT,  "DETTIME  ", &floatValue, "Total exposure time in seconds: NCOADDS x ITIME", &FitStatus);
    fits_write_key(fptr, TSTRING, "READMODE ", strValue,    "Readout mode", &FitStatus);
    fits_write_key(fptr, TINT,    "NREADS   ", &intValue,   "# reads at beg, end or during ITIME", &FitStatus);


    fits_write_record(fptr, "        ------------------------------------------------------------------------", &FitStatus);
    fits_write_key(fptr, TSTRING, "SPCTYPE1   ", (char *) "WAVE", "Pixel coordinate system ", &FitStatus);
    fits_write_key(fptr, TSTRING, "SPCTYPE2   ", strValue, "", &FitStatus);
    fits_write_key(fptr, TSTRING, "SPCTYPE3   ", strValue, "", &FitStatus);
    fits_write_key(fptr, TSTRING, "SPCUNIT1   ", strValue, "Unit of coordinate transformation", &FitStatus);
    fits_write_key(fptr, TSTRING, "SPCUNIT2   ", strValue, "Unit of coordinate transformation", &FitStatus);
    fits_write_key(fptr, TSTRING, "SPCUNIT3   ", strValue, "Unit of coordinate transformation", &FitStatus);
    fits_write_key(fptr, TFLOAT,  "SPCRVAL1   ", &floatValue, "Wavelength at CRPIX1", &FitStatus);
    fits_write_key(fptr, TFLOAT,  "SPCRVAL2   ", &floatValue, "RA at CRPIX1 in units CUNIT1", &FitStatus);
    fits_write_key(fptr, TFLOAT,  "SPCRVAL3   ", &floatValue, "DEC at CRPIX2 in units CUNIT2", &FitStatus);
    fits_write_key(fptr, TFLOAT,  "SPCD1_1    ", &floatValue, "Increment for CTYPE1", &FitStatus);
    fits_write_key(fptr, TFLOAT,  "SPCD2_2    ", &floatValue, "Increment for CTYPE2", &FitStatus);
    fits_write_key(fptr, TFLOAT,  "SPCD3_3    ", &floatValue, "Increment for CTYPE3", &FitStatus);
    fits_write_key(fptr, TINT,    "DISPAXIS ", &intValue, "Dispersion axis (1=rows; 2=columns)", &FitStatus);
    fits_write_key(fptr, TSTRING, "DISPUNIT ", strValue, "Units for coordinate along DISPAXIS", &FitStatus);
    fits_write_key(fptr, TSTRING, "DISPWC   ", strValue, "Approximate central dispersion coordinate on detector [DISPAXIS]", &FitStatus);
    fits_write_key(fptr, TSTRING, "DISPDW   ", strValue, "Approximate central dispersion per pixel on the detector [DISPAXIS/pxl]", &FitStatus);

    // Possible values are
    //  - FLUX when the image is produced by SHARKNIR-CAL-SCI-02
    //  - WAFFLE when the image is produced by SHARKNIR-CAL-SCI-08
    //  - OBJECT in all other cases
    fits_write_record(fptr, "        ------------------------------------------------------------------------", &FitStatus);
    fits_write_key(fptr, TSTRING, "HIERARCH LBT DPR TYPE", strValue, "", &FitStatus);

    SInstrumentHeader & ih = m_instrumentHeader;
    fits_write_key(fptr, TSTRING, "HIERARCH LBT INS MECH1 NAME", su::get_char_star(ih.inbeam_dep.nameid), "", &FitStatus);
    fits_write_key(fptr, TINT,    "HIERARCH LBT INS MECH1 ID",   &ih.inbeam_dep.mechanical_id, "General mechanical device unique ID", &FitStatus);
    fits_write_key(fptr, TLOGICAL,"HIERARCH LBT INS MECH1 ST",   &ih.inbeam_dep.status,    "T Deployed F Non Deployed", &FitStatus);
//    fits_write_key(fptr, TFLOAT,  "HIERARCH LBT INS MECH1 POS",  &ih.inbeam_dep.position1, "Position axis [um]", &FitStatus);
    fits_write_key(fptr, TINT,    "HIERARCH LBT INS MECH1 ENC",  &ih.inbeam_dep.encoder1,  "Position axis [enc]", &FitStatus);
    fits_write_key(fptr, TSTRING, "HIERARCH LBT INS MIRR1 NAME", su::get_char_star(ih.inbeam_tt.nameid), "", &FitStatus);
    fits_write_key(fptr, TFLOAT,  "HIERARCH LBT INS MIRR1 POS1", &ih.inbeam_tt.position1, "Position of axis 1 [mm]", &FitStatus);
    fits_write_key(fptr, TFLOAT,  "HIERARCH LBT INS MIRR1 POS2", &ih.inbeam_tt.position2, "Position of axis 2 [mm]", &FitStatus);
    fits_write_key(fptr, TINT,    "HIERARCH LBT INS MIRR1 ENC1", &ih.inbeam_tt.encoder1,  "Position of axis 1 [enc]", &FitStatus);
    fits_write_key(fptr, TINT,    "HIERARCH LBT INS MIRR1 ENC2", &ih.inbeam_tt.encoder2,  "Position of axis 2 [enc]", &FitStatus);
    fits_write_key(fptr, TSTRING, "HIERARCH LBT INS SHUT1 NAME", su::get_char_star(ih.shutter.nameid), "", &FitStatus);
    fits_write_key(fptr, TLOGICAL,"HIERARCH LBT INS SHUT1 ST",   &ih.shutter.status,    "T Shutter open", &FitStatus);
//    fits_write_key(fptr, TFLOAT,  "HIERARCH LBT INS SHUT1 POS",  &ih.shutter.position1, "Position of axis [um]", &FitStatus);
    fits_write_key(fptr, TINT,    "HIERARCH LBT INS SHUT1 ENC",  &ih.shutter.encoder1,  "Position of axis [enc]", &FitStatus);

    fits_write_record(fptr, "        ------------------------------------------------------------------------", &FitStatus);

    fits_write_key(fptr, TSTRING, "HIERARCH LBT INS MIRR3 NAME", su::get_char_star(ih.cal_mirror_dep.nameid), "Name of optical element", &FitStatus);
    fits_write_key(fptr, TINT,    "HIERARCH LBT INS MIRR3 ID",   &ih.cal_mirror_dep.mechanical_id, "ID of the element", &FitStatus);
    fits_write_key(fptr, TLOGICAL,"HIERARCH LBT INS MIRR3 ST",   &ih.cal_mirror_dep.status,    "Status of deployable mirror", &FitStatus);
    fits_write_key(fptr, TFLOAT,  "HIERARCH LBT INS MIRR3 POS",  &ih.cal_mirror_dep.position1, "Position of axis [mm]", &FitStatus);
    fits_write_key(fptr, TINT,    "HIERARCH LBT INS MIRR3 ENC",  &ih.cal_mirror_dep.encoder1,  "Position of axis [enc]", &FitStatus);
    fits_write_key(fptr, TSTRING, "HIERARCH LBT INS OPTI4 NAME", su::get_char_star(ih.cal_filter_dep.nameid), "Name of optical element ", &FitStatus);
    fits_write_key(fptr, TSTRING, "HIERARCH LBT INS OPTI4 TYPE", su::get_char_star(ih.cal_filter_dep.type), "Named Position if any", &FitStatus);
    fits_write_key(fptr, TINT,    "HIERARCH LBT INS OPTI4 ID",   &ih.cal_filter_dep.mechanical_id, "ID of the element", &FitStatus);
    fits_write_key(fptr, TFLOAT,  "HIERARCH LBT INS OPTI4 POS",  &ih.cal_filter_dep.position1, "Position of axis [mm]", &FitStatus);
    fits_write_key(fptr, TINT,    "HIERARCH LBT INS OPTI4 ENC",  &ih.cal_filter_dep.encoder1,  "Position of axis [enc]", &FitStatus);
    fits_write_key(fptr, TSTRING, "HIERARCH LBT INS OPTI5 NAME", su::get_char_star(ih.cal_fiber_dep.nameid), "Name of optical element ", &FitStatus);
    fits_write_key(fptr, TSTRING, "HIERARCH LBT INS OPTI5 TYPE", su::get_char_star(ih.cal_fiber_dep.type),   "Named Position if any", &FitStatus);
    fits_write_key(fptr, TINT,    "HIERARCH LBT INS OPTI5 ID",   &ih.cal_fiber_dep.mechanical_id, "ID of the element", &FitStatus);
    fits_write_key(fptr, TFLOAT,  "HIERARCH LBT INS OPTI5 POS",  &ih.cal_fiber_dep.position1, "Position of axis [mm]", &FitStatus);
    fits_write_key(fptr, TINT,    "HIERARCH LBT INS OPTI5 ENC",  &ih.cal_fiber_dep.encoder1,  "Position of axis [enc]", &FitStatus);
    fits_write_key(fptr, TSTRING, "HIERARCH LBT INS SENS1 NAME", su::get_char_star(ih.cal_flat_field_lamp.nameid), "Sensor common name for flat field lamp ", &FitStatus);
    fits_write_key(fptr, TINT,    "HIERARCH LBT INS SENS1 ID",   &ih.cal_flat_field_lamp.mechanical_id, "Sensor ID for OPTI5 ", &FitStatus);
    fits_write_key(fptr, TLOGICAL,"HIERARCH LBT INS SENS1 VAL",  &ih.cal_flat_field_lamp.status, "T for ON, F for OFF ", &FitStatus);
    fits_write_key(fptr, TSTRING, "HIERARCH LBT INS SENS2 NAME", su::get_char_star(ih.cal_fiber_focus_lamp.nameid), "Sensor common name for fiber lamp ", &FitStatus);
    fits_write_key(fptr, TINT,    "HIERARCH LBT INS SENS2 ID",   &ih.cal_fiber_focus_lamp.mechanical_id, "Sensor ID for OPTI6 ", &FitStatus);
    fits_write_key(fptr, TLOGICAL,"HIERARCH LBT INS SENS2 VAL",  &ih.cal_fiber_focus_lamp.status, "T for ON, F for OFF ", &FitStatus);
    fits_write_key(fptr, TSTRING, "HIERARCH LBT INS SENS3 NAME", su::get_char_star(ih.cal_fiber_defocus_lamp.nameid), "Sensor common name for fiber lamp ", &FitStatus);
    fits_write_key(fptr, TINT,    "HIERARCH LBT INS SENS3 ID",   &ih.cal_fiber_defocus_lamp.mechanical_id, "Sensor ID for OPTI6 ", &FitStatus);
    fits_write_key(fptr, TLOGICAL,"HIERARCH LBT INS SENS3 VAL",  &ih.cal_fiber_defocus_lamp.status, "T for ON, F for OFF ", &FitStatus);

    fits_write_record(fptr, "        ------------------------------------------------------------------------", &FitStatus);

    fits_write_key(fptr, TSTRING, "HIERARCH LBT INS MIRR2 NAME", (char *) "PUPIL_TT", "", &FitStatus);
    fits_write_key(fptr, TFLOAT,  "HIERARCH LBT INS MIRR2 POS1", &floatValue, "Position of axis 1 [um]", &FitStatus);
    fits_write_key(fptr, TFLOAT,  "HIERARCH LBT INS MIRR2 POS2", &floatValue, "Position of axis 2 [um]", &FitStatus);
    fits_write_key(fptr, TINT,    "HIERARCH LBT INS MIRR2 ENC1", &intValue, "Position of axis 1 [enc]", &FitStatus);
    fits_write_key(fptr, TINT,    "HIERARCH LBT INS MIRR2 ENC2", &intValue, "Position of axis 2 [enc]", &FitStatus);

    fits_write_record(fptr, "        ------------------------------------------------------------------------", &FitStatus);

    fits_write_key(fptr, TSTRING, "HIERARCH LBT INS FILT1 NAME", su::get_char_star(ih.nd_filt_w.nameid), "Name of optical element", &FitStatus);
    fits_write_key(fptr, TSTRING, "HIERARCH LBT INS FILT1 NP",   su::get_char_star(ih.nd_filt_w.type),   "Named position if any", &FitStatus);
    fits_write_key(fptr, TINT,    "HIERARCH LBT INS FILT1 NO",   &ih.nd_filt_w.intValue, "Position of wheel used", &FitStatus);
    fits_write_key(fptr, TINT,    "HIERARCH LBT INS FILT1 ID",   &ih.nd_filt_w.mechanical_id, "ID of the element", &FitStatus);
    fits_write_key(fptr, TFLOAT,  "HIERARCH LBT INS FILT1 POS",  &ih.nd_filt_w.position1, "Position of axis [deg]", &FitStatus);
    fits_write_key(fptr, TINT,    "HIERARCH LBT INS FILT1 ENC",  &ih.nd_filt_w.encoder1, "Position of axis [enc]", &FitStatus);

    fits_write_key(fptr, TSTRING, "HIERARCH LBT INS OPTI1 NAME", su::get_char_star(ih.apodizer_w.nameid), "Name of optical element", &FitStatus);
    fits_write_key(fptr, TSTRING, "HIERARCH LBT INS OPTI1 NP",   su::get_char_star(ih.apodizer_w.type),   "Named position if any", &FitStatus);
    fits_write_key(fptr, TINT,    "HIERARCH LBT INS OPTI1 NO",   &ih.apodizer_w.intValue, "Position of wheel used", &FitStatus);
    fits_write_key(fptr, TINT,    "HIERARCH LBT INS OPTI1 ID",   &ih.apodizer_w.mechanical_id, "ID of the element", &FitStatus);
    fits_write_key(fptr, TFLOAT,  "HIERARCH LBT INS OPTI1 POS",  &ih.apodizer_w.position1, "Position of axis [deg]", &FitStatus);
    fits_write_key(fptr, TINT,    "HIERARCH LBT INS OPTI1 ENC",  &ih.apodizer_w.encoder1, "Position of axis [enc]", &FitStatus);

    fits_write_key(fptr, TSTRING, "HIERARCH LBT INS OPTI2 NAME", su::get_char_star(ih.coro_slit_w.nameid), "Name of optical element", &FitStatus);
    fits_write_key(fptr, TSTRING, "HIERARCH LBT INS OPTI2 NP",   su::get_char_star(ih.coro_slit_w.type),   "Named position if any", &FitStatus);
    fits_write_key(fptr, TINT,    "HIERARCH LBT INS OPTI2 NO",   &ih.coro_slit_w.intValue, "Position of wheel used", &FitStatus);
    fits_write_key(fptr, TINT,    "HIERARCH LBT INS OPTI2 ID",   &ih.coro_slit_w.mechanical_id, "ID of the element", &FitStatus);
    fits_write_key(fptr, TFLOAT,  "HIERARCH LBT INS OPTI2 POS",  &ih.coro_slit_w.position1, "Position of axis [deg]", &FitStatus);
    fits_write_key(fptr, TINT,    "HIERARCH LBT INS OPTI2 ENC",  &ih.coro_slit_w.encoder1, "Position of axis [enc]", &FitStatus);

    fits_write_key(fptr, TSTRING, "HIERARCH LBT INS OPTI3 NAME", su::get_char_star(ih.lyot_grism_w.nameid), "Name of optical element", &FitStatus);
    fits_write_key(fptr, TSTRING, "HIERARCH LBT INS OPTI3 NP",   su::get_char_star(ih.lyot_grism_w.type),   "Named position if any", &FitStatus);
    fits_write_key(fptr, TINT,    "HIERARCH LBT INS OPTI3 NO",   &ih.lyot_grism_w.intValue, "Position of wheel used", &FitStatus);
    fits_write_key(fptr, TINT,    "HIERARCH LBT INS OPTI3 ID",   &ih.lyot_grism_w.mechanical_id, "ID of the element", &FitStatus);
    fits_write_key(fptr, TFLOAT,  "HIERARCH LBT INS OPTI3 POS",  &ih.lyot_grism_w.position1, "Position of axis [deg]", &FitStatus);
    fits_write_key(fptr, TINT,    "HIERARCH LBT INS OPTI3 ENC",  &ih.lyot_grism_w.encoder1, "Position of axis [enc]", &FitStatus);

    fits_write_key(fptr, TSTRING, "HIERARCH LBT INS FILT2 NAME", su::get_char_star(ih.sci_filt_w1.nameid), "Name of optical element", &FitStatus);
    fits_write_key(fptr, TSTRING, "HIERARCH LBT INS FILT2 NP",   su::get_char_star(ih.sci_filt_w1.type),   "Named Position if any", &FitStatus);
    fits_write_key(fptr, TINT,    "HIERARCH LBT INS FILT2 NO",   &ih.sci_filt_w1.status, "Position of wheel used", &FitStatus);
    fits_write_key(fptr, TINT,    "HIERARCH LBT INS FILT2 ID",   &ih.sci_filt_w1.mechanical_id, "ID of the element", &FitStatus);
    fits_write_key(fptr, TFLOAT,  "HIERARCH LBT INS FILT2 POS",  &ih.sci_filt_w1.position1, "Position of axis [deg]", &FitStatus);
    fits_write_key(fptr, TINT,    "HIERARCH LBT INS FILT2 ENC",  &ih.sci_filt_w1.encoder1, "Position of axis [enc]", &FitStatus);

    fits_write_key(fptr, TSTRING, "HIERARCH LBT INS FILT3 NAME", su::get_char_star(ih.sci_filt_w2.nameid), "Name of optical element", &FitStatus);
    fits_write_key(fptr, TSTRING, "HIERARCH LBT INS FILT3 NP",   su::get_char_star(ih.sci_filt_w2.type),   "Named position if any", &FitStatus);
    fits_write_key(fptr, TINT,    "HIERARCH LBT INS FILT3 NO",   &ih.sci_filt_w2.intValue, "Position of wheel used", &FitStatus);
    fits_write_key(fptr, TINT,    "HIERARCH LBT INS FILT3 ID",   &ih.sci_filt_w2.mechanical_id, "ID of the element", &FitStatus);
    fits_write_key(fptr, TFLOAT,  "HIERARCH LBT INS FILT3 POS",  &ih.sci_filt_w2.position1, "Position of axis [deg]", &FitStatus);
    fits_write_key(fptr, TINT,    "HIERARCH LBT INS FILT3 ENC",  &ih.sci_filt_w2.encoder1, "Position of axis [enc]", &FitStatus);

    fits_write_key(fptr, TSTRING, "HIERARCH LBT INS MECH2 NAME", su::get_char_star(ih.pupil_lens_dep.nameid), "Name of the optical element", &FitStatus);
    fits_write_key(fptr, TINT,    "HIERARCH LBT INS MECH2 ID",   &ih.pupil_lens_dep.mechanical_id, "General mechanical device unique ID", &FitStatus);
    fits_write_key(fptr, TLOGICAL,"HIERARCH LBT INS MECH2 ST",   &ih.pupil_lens_dep.status, "T deployed; F not deployed", &FitStatus);
    fits_write_key(fptr, TFLOAT,  "HIERARCH LBT INS MECH2 POS",  &ih.pupil_lens_dep.position1, "Position axis [um]", &FitStatus);
    fits_write_key(fptr, TINT,    "HIERARCH LBT INS MECH2 ENC",  &ih.pupil_lens_dep.encoder1, "Position axis [enc]", &FitStatus);

    fits_write_key(fptr, TSTRING, "HIERARCH LBT INS FILT4 NAME", su::get_char_star(ih.db_filt_w.nameid), "Name of optical element", &FitStatus);
    fits_write_key(fptr, TSTRING, "HIERARCH LBT INS FILT4 NP",   su::get_char_star(ih.db_filt_w.type),   "Named position if any", &FitStatus);
    fits_write_key(fptr, TINT,    "HIERARCH LBT INS FILT4 NO",   &ih.db_filt_w.intValue, "Position of wheel used", &FitStatus);
    fits_write_key(fptr, TINT,    "HIERARCH LBT INS FILT4 ID",   &ih.db_filt_w.mechanical_id, "ID of the element", &FitStatus);
    fits_write_key(fptr, TFLOAT,  "HIERARCH LBT INS FILT4 POS",  &ih.db_filt_w.position1, "Position of axis [deg]", &FitStatus);
    fits_write_key(fptr, TINT,    "HIERARCH LBT INS FILT4 ENC",  &ih.db_filt_w.encoder1, "Position of axis [enc]", &FitStatus);

    fits_write_key(fptr, TSTRING, "HIERARCH LBT INS DROT NAME",  su::get_char_star(ih.derotator.nameid), "", &FitStatus);
    fits_write_key(fptr, TINT,    "HIERARCH LBT INS DROT ID",    &ih.derotator.mechanical_id, "General mechanical device unique ID", &FitStatus);
    fits_write_key(fptr, TSTRING, "HIERARCH LBT INS DROT MODE",  su::get_char_star(ih.derotator.type), "Instrument derotator mode", &FitStatus);
    fits_write_key(fptr, TFLOAT,  "HIERARCH LBT INS DROT POS",   &ih.derotator.position1, "Position axis [deg]", &FitStatus);
    fits_write_key(fptr, TINT,    "HIERARCH LBT INS DROT ENC",   &ih.derotator.encoder1, "Position axis [enc]", &FitStatus);
    fits_write_key(fptr, TINT,    "HIERARCH LBT INS DROT ABSENC",&ih.derotator.encoder2, "Position axis [absenc]", &FitStatus);
    fits_write_key(fptr, TFLOAT,  "HIERARCH LBT INS DROT BEGIN", &ih.derotator.position2, "Physical position at start [deg]", &FitStatus);

    fits_write_key(fptr, TSTRING, "HIERARCH LBT INS ADC NAME",   su::get_char_star(ih.adc.nameid), "", &FitStatus);
    fits_write_key(fptr, TLOGICAL,"HIERARCH LBT INS ADC ST",     &ih.adc.status, "T when the (sub)system is on, F when off", &FitStatus);
    fits_write_key(fptr, TFLOAT,  "HIERARCH LBT INS ADC1 POS",   &ih.adc.position1, "Position of axis 1 [deg]", &FitStatus);
    fits_write_key(fptr, TFLOAT,  "HIERARCH LBT INS ADC2 POS",   &ih.adc.position2, "Position of axis 2 [deg]", &FitStatus);
    fits_write_key(fptr, TINT,    "HIERARCH LBT INS ADC1 ENC",   &ih.adc.encoder1, "Position of axis 1 [enc]", &FitStatus);
    fits_write_key(fptr, TINT,    "HIERARCH LBT INS ADC2 ENC",   &ih.adc.encoder2, "Position of axis 2 [enc]", &FitStatus);

    fits_write_key(fptr, TFLOAT,  "HIERARCH LBT INS TEMP1 VAL BEGIN", &ih.temperature_start, "Cryo-vacuum T [K] at observation start ", &FitStatus);
    fits_write_key(fptr, TFLOAT,  "HIERARCH LBT INS TEMP1 VAL END ",  &ih.temperature_end, "Cryo-vacuum T [K] at end of observation", &FitStatus);


    // TODO : Table 10 Instrument setup keyword


    // TODO : Detector specific keywords


    // TODO : Table 11 Detector Setup keywords

    // TODO : Table 12 RTC Setup Keywords

    fits_write_record(fptr, "        ------------------------------------------------------------------------", &FitStatus);
    int WCSDIM = 2;
    fits_write_key(fptr, TINT,    "WCSDIM   ", &WCSDIM,     "Dimensionality of WCS: 2 for image, 3 for spectrum", &FitStatus);
    if(WCSDIM == 2)
    {
        fits_write_key(fptr, TSTRING, "CTYPE1   ", strValue,    "Pixel coordinate system", &FitStatus);
        fits_write_key(fptr, TSTRING, "CTYPE2   ", strValue,    "Pixel coordinate system", &FitStatus);
        fits_write_key(fptr, TSTRING, "CUNIT1   ", strValue,    "Unit of coordinate transformation", &FitStatus);
        fits_write_key(fptr, TSTRING, "CUNIT2   ", strValue,    "Unit of coordinate transformation", &FitStatus);
        fits_write_key(fptr, TFLOAT,  "CRPIX1   ", &floatValue, "Value of X Ref. pixel", &FitStatus);
        fits_write_key(fptr, TFLOAT,  "CRPIX2   ", &floatValue, "Value of Y Ref. pixel", &FitStatus);   
        fits_write_key(fptr, TFLOAT,  "CRVAL1   ", &floatValue, "RA at CRPIX1 in units CUNIT1", &FitStatus);
        fits_write_key(fptr, TFLOAT,  "CRVAL2   ", &floatValue, "DEC at CRPIX2 in units CUNIT2", &FitStatus);
        fits_write_key(fptr, TFLOAT,  "CDELT1   ", &floatValue2,"Increment along axis 1 as [CUNIT1]/pxl", &FitStatus);
        fits_write_key(fptr, TFLOAT,  "CDELT2   ", &floatValue2,"Increment along axis 2 as [CUNIT2]/pxl", &FitStatus);
        fits_write_key(fptr, TFLOAT,  "CD1_1    ", &floatValue, "Scale in [CUNIT1]/pixel", &FitStatus);
        fits_write_key(fptr, TFLOAT,  "CD1_2    ", &floatValue, "Rotation and skew", &FitStatus);
        fits_write_key(fptr, TFLOAT,  "CD2_1    ", &floatValue, "Rotation and skew", &FitStatus);
        fits_write_key(fptr, TFLOAT,  "CD2_2    ", &floatValue, "Scale in [CUNIT2]/pixel", &FitStatus);
        fits_write_key(fptr, TSTRING, "WAT0_001 ", strValue,    "Coordinate system", &FitStatus);
        fits_write_key(fptr, TSTRING, "WAT1_001 ", strValue,    "Coordinate type", &FitStatus);
        fits_write_key(fptr, TSTRING, "WAT2_001 ", strValue,    "Coordinate type", &FitStatus);
        fits_write_key(fptr, TINT,    "WCSSOL   ", &intValue,   "", &FitStatus);
    }
    else if(WCSDIM == 3)
    {
        fits_write_key(fptr, TSTRING, "CTYPE1   ", (char *)"WAVE",    "Pixel coordinate system", &FitStatus);
        fits_write_key(fptr, TSTRING, "CTYPE2   ", strValue,    "Pixel coordinate system", &FitStatus);
        fits_write_key(fptr, TSTRING, "CTYPE3   ", strValue,    "Pixel coordinate system", &FitStatus);
        fits_write_key(fptr, TSTRING, "CUNIT1   ", strValue,    "Unit of coordinate transformation", &FitStatus);
        fits_write_key(fptr, TSTRING, "CUNIT2   ", strValue,    "Unit of coordinate transformation", &FitStatus);
        fits_write_key(fptr, TSTRING, "CUNIT3   ", strValue,    "Unit of coordinate transformation", &FitStatus);
        fits_write_key(fptr, TFLOAT,  "CRVAL1   ", &floatValue, "Wavelength at CRPIX1", &FitStatus);
        fits_write_key(fptr, TFLOAT,  "CRVAL2   ", &floatValue, "RA at CRPIX1 in units CUNIT1", &FitStatus);
        fits_write_key(fptr, TFLOAT,  "CRVAL3   ", &floatValue, "DEC at CRPIX2 in units CUNIT2", &FitStatus);
        fits_write_key(fptr, TFLOAT,  "CD1_1    ", &floatValue, "Increment for CTYPE1", &FitStatus);
        fits_write_key(fptr, TFLOAT,  "CD2_2    ", &floatValue, "Increment for CTYPE2", &FitStatus);
        fits_write_key(fptr, TFLOAT,  "CD3_3    ", &floatValue, "Increment for CTYPE3", &FitStatus);
        fits_write_key(fptr, TINT,    "DISPAXIS ", &intValue,   "Dispersion axis (1=rows; 2=columns)", &FitStatus);
        fits_write_key(fptr, TSTRING, "DISPUNIT ", strValue,    "Units for coordinate along DISPAXIS", &FitStatus);
        fits_write_key(fptr, TSTRING, "DISPWC   ", strValue,    "Approximate central dispersion coordinate on detector [DISPAXIS]", &FitStatus);
        fits_write_key(fptr, TSTRING, "DISPDW   ", strValue,    "Approximate central dispersion per pixel on the detector", &FitStatus);
    }
   
   // TODO : Table 15 Enclosure, environment, and weather specific keywords
    fits_write_record(fptr, "        ------------------------------------------------------------------------", &FitStatus);
    fits_write_key(fptr, TFLOAT,  "DOMEPAN  ", &floatValue, "Dome position angle [degrees E of N]", &FitStatus);
    fits_write_key(fptr, TFLOAT,  "DOMTEM   ", &floatValue, "Dome temperature [degrees C]", &FitStatus);
    fits_write_key(fptr, TFLOAT,  "DOMHUM   ", &floatValue, "Dome relative humidity [%]", &FitStatus);
    fits_write_key(fptr, TFLOAT,  "DOMDEWPT ", &floatValue, "Dome dew point [degrees C]", &FitStatus);

    fits_write_record(fptr, "        ------------------------------------------------------------------------", &FitStatus);
    fits_write_key(fptr, TFLOAT,  "ENVTEM   ", &floatValue, "Outside temperature, C, at MJD-OBS", &FitStatus);
    fits_write_key(fptr, TFLOAT,  "ENVPRE   ", &floatValue, "Atmospheric pressure [mbar]", &FitStatus);
    fits_write_key(fptr, TFLOAT,  "ENVWIN   ", &floatValue, "Outside wind speed (m/s) at MJD-OBS", &FitStatus);
    fits_write_key(fptr, TFLOAT,  "ENVDIR   ", &floatValue, "(degrees) Direction of wind: E from N", &FitStatus);
    fits_write_key(fptr, TFLOAT,  "ENVHUM   ", &floatValue, "Outside relative humidity % at MJD-OBS", &FitStatus);
    fits_write_key(fptr, TFLOAT,  "ENVDEWPT ", &floatValue, "Outside dew point (degrees C) at MJD-OBS", &FitStatus);
    fits_write_key(fptr, TFLOAT,  "ENVTAU   ", &floatValue, "Opacity at 225 GHz, from SMT", &FitStatus);
    fits_write_key(fptr, TSTRING, "WEATHER  ", strValue,    "Comment by telescope operator or observer", &FitStatus);
    fits_write_key(fptr, TFLOAT,  "SEEING   ", &floatValue, "Seeing estimate from S-H WFS", &FitStatus);
    fits_write_key(fptr, TFLOAT,  "SEEWAV   ", &floatValue, "Wavelength for seeing estimate", &FitStatus);
    fits_write_key(fptr, TFLOAT,  "SEECAL   ", &floatValue, "Seeing: S-H to seeing calibration curve", &FitStatus);

    U8_LLOG("");
    return FitStatus;
}


void SeqDataMgr::getTelescopeEnv(STelescopeEnv & env)
{

    // DIMMFWHM                 DIMM seeing, [arcsecs]                      DIMMSeeing (DIMMSeeingZenith, DIMMSeeingElevation)
    // DIMMFLUX                 DIMM mean centroid flux                     DIMMMeanFlux
    // LBTWLINK                 Weather Station Link State                  LBTWeatherAlive (LBTWeatherAliveFront)
    // LBTPRES                  Ambient Pressure [hPa]                      LBTPressure
    // LBTTEMP                  Ambient Temperature [deg C]                 LBTTemp
    // LBTHUM                   LBT Relative Humidity [percent]             LBTHumidity
    // LBTDWPT                  LBT Dew Point [deg C]                       LBTDewPoint
    lbto::result res;
    lbto::DDstruct ddt;
    lbto::SeqDD dd;
    ddt.DDname = "DIMMSeeing";
    dd.push_back(ddt);
    ddt.DDname = "DIMMMeanFlux";
    dd.push_back(ddt);
    ddt.DDname = "LBTWeatherAlive";
    dd.push_back(ddt);
    ddt.DDname = "LBTPressure";
    dd.push_back(ddt);
    ddt.DDname = "LBTTemp";
    dd.push_back(ddt);
    ddt.DDname = "LBTHumidity";
    dd.push_back(ddt);
    ddt.DDname = "LBTDewPoint";
    dd.push_back(ddt);
    res = m_iif->iifGetParameter(dd);
    if(res.rescode == EXIT_SUCCESS)
    {
        double temp;
        env.dimm_seeing = atof(res.resmsg[1].c_str());
        env.dimm_mean_flux = atof(res.resmsg[2].c_str());
        env.lbt_weather_alive = (bool)atoi(res.resmsg[3].c_str());
        env.lbt_pressure = atof(res.resmsg[4].c_str());
        env.lbt_temp = atof(res.resmsg[5].c_str());
        env.lbt_humidity = atof(res.resmsg[6].c_str());
        env.lbt_dewpoint = atof(res.resmsg[7].c_str());
    }
    else
    {
        for(unsigned int i = 0; i < res.resmsg.size(); i++)
        {
            U9_LLOG(res.resmsg[i]);
        }
    }
}

int SeqDataMgr::sashaEnableSave(const std::map<std::string, std::string> & _dSashaSetup)
{
    // To be Implemented
    U6_LLOG(__FUNCTION__ << " ~ DEPRECATED");
    Ice::Int status = EXIT_SUCCESS;
#ifdef UNDEFINED
    IProperty sashaSave(IProperty::Switch), recvProp;
    std::map<std::string, std::string>::const_iterator itFind;
    itFind = _dSashaSetup.find("SAVE");

    // m_ptrIc->connect();
    // NOTE while alive, indiserver does not close the connection to the client.
    // U1_LLOG("Command sasha to save to file");
    U1_LLOG("Command sasha to save to file");

    sashaSave.setDevice("sasha_save");
    sashaSave.setName("enable_save");
    sashaSave.setPerm(IProperty::ReadWrite);
    sashaSave.setState(IProperty::Busy);
    sashaSave.add(IElement("value"));
    // Switch properties can have value On or Off
    sashaSave["value"].setSwitchState(IElement::Off);
    U1_LLOG(sashaSave.getType());
    if (!(itFind == _dSashaSetup.end()))
    {
        if ((su::str_tolower(itFind->second) == "true") || (itFind->second == "1"))
        {
            sashaSave["value"].setSwitchState(IElement::On);
        }
    }

    //
    m_ptrIc2->send_new_property_wait2(sashaSave, recvProp);
#endif
    // status = m_ptrIc->close();
    U8_LLOG(__FUNCTION__);
    return status;
}


int SeqDataMgr::sashaGetFitsFile(const std::map<std::string, std::string> & _dSashaSetup, const std::string & _instMode, std::string & _outFilename)
{
    U6_LLOG(__FUNCTION__ << " ~ DEPRECATED");
    int status = EXIT_FAILURE;
#ifdef UNDEFINED
        std::string strObjname = "test";
        Ice::CommunicatorPtr dataMgrIC;
        // std::ostringstream streamRsync;
        // std::ostringstream streamFileNum;
        // std::ostringstream streamFileName;
        std::ofstream fout;
        // --Ice.Config=$INSROOT/etc/data_mgr/data_mgr-ice.cfg
    //    char* argvDataMgr[] = { "SequencerI::sashaGetFITSFile",
    //                           "--Ice.Config=/opt/tan/etc/data_mgr/data_mgr-ice.cfg" };
    //    int argcDataMgr = 2;

        // CFITSIO related
                           //
                            // Saving file to disk
                            // filename format is SHARKNIR.YYYY-MM-DDThh:mm:ss.ssssssZ.<_instMode>.fits
                            // this is passed to data manager for future use in mearging headers
                            // and saved in output parameter
                            //

                            // get date of file creation by INDI in ISO8601 format
                            dateISO8601 = recvProp.getTimeStamp().getFormattedIso8601Str();

                            filenameSASHA = "SHARKNIR." + dateISO8601 + "." + _instMode + ".SASHA.fits";

                            filenameSHINS = "SHARKNIR." + dateISO8601 + "." + _instMode + ".fits";


                            /* what follows is most likely old code to be erased
                             at this moment dataMgr will take care of ingesting file to
                             LBT archive mount point

                             // setting filenameSASHA as filename of acquired FITS file to data_mgr for its reference
                             // NOTE: may not be necessary
                             dataMgrIC = Ice::initialize(argcDataMgr, argvDataMgr);
                             Ice::ObjectPrx base = dataMgrIC->stringToProxy("dataManagerAdapter:default -p 10501");
                             sd::fitsFilePrx archiver = sd::fitsFilePrx::checkedCast(base);
                             if (!archiver)