/** @class SofieDBinput.cpp @author Brian Magill @datecreated 7/12/2006 $Date: 2006/04/07 14:14:54 $ $Revision: 1.3 $ @copyright (©) Copyright 2006 by GATS Inc. 11864 Canon Blvd., Suite 101, Newport News, VA 23606 All Rights Reserved. No part of this software or publication may be reproduced, stored in a retrieval system, or transmitted, in any form or by any means, electronic, mechanical, photocopying, recording, or otherwise without the prior written permission of GATS Inc. @brief Class for reading Level 0 science data for a particular event */ //---------------------------------------------------------------------- // #include #include #include #include "SofieDBinput.h" #include "DetectorSample.h" //#include "STrackerSignal.h" #include "SunSensorData.h" #include "SunSensorSample.h" #include "FilterTSample.h" #include "MiscExceptions.h" #include "GATS_Utilities.hpp" using namespace SOFIE; using namespace std; using namespace gatsDBpp; using namespace GATS_Utilities; /// Construct a SofieDBinput object /// /// @param db - Database parameter object /// @param event - event number /// SofieDBinput::SofieDBinput(DBInputParam const &db, long const &event) { dbParam = db; hasData = false; header = ReadLvl0Header(event); } /// Read Level 0 event summary information. This is a private /// helper method. /// /// @param event_number - number of event since start of mission /// Lvl0FileHeader SofieDBinput::ReadLvl0Header(long const &event_number) { // long i; Lvl0FileHeader Aheader; string event_type; int orbit_number; double event_start_time; double event_end_time; double occult_start_time; double occult_end_time; int table_number; double solar_scan_start_time; double solar_scan_end_time; GATS_DB_Results dbResults; string version_id; string tableName; string sqlString; GATS_DB *dbIn = dbParam.getDBConn(); tableName = dbParam.getSofieSummaryTable(); version_id = dbParam.getVersionID(); sqlString = string("SELECT EVENT_TYPE, TABLE_NUMBER, ORBIT_NUMBER, ") + "UNIX_TIMESTAMP(BEGIN_TIME), UNIX_TIMESTAMP(END_TIME), " + "UNIX_TIMESTAMP(OCC_START_TIME),UNIX_TIMESTAMP(OCC_END_TIME), " + "UNIX_TIMESTAMP(CAL_START_TIME), UNIX_TIMESTAMP(CAL_END_TIME) FROM " + tableName + " WHERE EVENT_NUMBER = " + ConvertToString(event_number) + " AND VERSION_ID = '" + version_id + "'"; try { dbResults = dbIn->Query(sqlString.c_str()); } catch (GATS_Exception &ex) { string errStr = string("SofieDBinput::Problem with Header data for event") + ConvertToString(header.getEventNumber()) + ", message: " + ex.what(); cerr << errStr << endl; THROW_GATS_EXCEPTION(IOException, errStr); } if(dbResults.size() > 1) { string errStr = string("ReadLvl0Header::Wrong number of lines retrieved"); cerr << errStr << endl; THROW_GATS_EXCEPTION(IOException, errStr); } else if (dbResults.size() == 1) { hasData = true; event_type = dbResults[0][0].asString(); table_number = dbResults[0][1].asInt(); orbit_number = dbResults[0][2].asInt(); event_start_time = dbResults[0][3].asLong(); event_end_time = dbResults[0][4].asLong(); occult_start_time= dbResults[0][5].asLong(); occult_end_time = dbResults[0][6].asLong(); solar_scan_start_time= dbResults[0][7].asLong(); solar_scan_end_time = dbResults[0][8].asLong(); } else { hasData = false; event_type = "?"; table_number = 0; orbit_number = 0; event_start_time = 0; event_end_time = 0; occult_start_time= 0; occult_end_time = 0; solar_scan_start_time= 0; solar_scan_end_time = 0; } Aheader = Lvl0FileHeader(event_number, event_type, table_number, orbit_number, event_start_time, event_end_time, occult_start_time, occult_end_time, solar_scan_start_time, solar_scan_end_time); return Aheader; } /// Read data for a given event /// @param event - number of event since start of mission /// void SofieDBinput::Read(long const &event) { header = ReadLvl0Header(event); } /// Returns the solar tracking information for the current event /// SunSensorData SofieDBinput::getSunSensorData() { string sqlString; double sampletime; long time; long msec; double X_Low; // left edge double X_High; // right edge double Y_Low; // bottom edge double Y_High; // top edge int trackStatus; // tracking status double Elev; // actual elevation double Azim; // actual azimuth SunSensorData SSData; vector SSSamples; vector Sums(NSums); string trackTableName = dbParam.getSolarTrackingTable(); string imageTableName = dbParam.getSolarImageTable(); string version_id = dbParam.getVersionID(); GATS_DB *dbIn = dbParam.getDBConn(); long begin_time = static_cast (header.getEventStart() ); long end_time = static_cast (header.getEventEnd() + 0.5); GATS_DB_Results dbResults; sqlString = string("SELECT UNIX_TIMESTAMP(B.PIXEL_TIME_STAMP),B.SAMPLE_MICROSECONDS,") + "A.LOW_X_FPA_COORDINATES, A.HIGH_X_FPA_COORDINATES, " + "A.LOW_Y_FPA_COORDINATES, A.HIGH_Y_FPA_COORDINATES, " + "A.TRACKING_RETURN_VALUE, A.ACTUAL_MIRROR_ELEVATION, " + "A.ACTUAL_MIRROR_AZIMUTH, " + "B.LOW_X_SUM_1, B.LOW_X_SUM_2, " + "B.LOW_X_SUM_3, B.LOW_X_SUM_4, " + "B.LOW_X_SUM_5, B.LOW_X_SUM_6, B.LOW_X_SUM_7, " + "B.HIGH_X_SUM_1, B.HIGH_X_SUM_2, " + "B.HIGH_X_SUM_3, B.HIGH_X_SUM_4, " + "B.HIGH_X_SUM_5, B.HIGH_X_SUM_6, B.HIGH_X_SUM_7, " + "B.LOW_Y_SUM_1, B.LOW_Y_SUM_2, " + "B.LOW_Y_SUM_3, B.LOW_Y_SUM_4, B.LOW_Y_SUM_5, " + "B.HIGH_Y_SUM_1, B.HIGH_Y_SUM_2, " + "B.HIGH_Y_SUM_3, B.HIGH_Y_SUM_4, B.HIGH_Y_SUM_5, " + "B.CENTER_SUM_1, B.CENTER_SUM_2, " + "B.CENTER_SUM_3, B.CENTER_SUM_4, " + "B.CENTER_SUM_5, B.CENTER_SUM_6, B.CENTER_SUM_7 " + "FROM " + trackTableName + " as A, " + imageTableName + " as B " + "WHERE A.PACKET_ID = B.PACKET_ID " + "AND A.SAMPLE_NUMBER = B.SAMPLE_NUMBER " + "AND B.VERSION_ID = '" + version_id + "' " + "AND B.PIXEL_TIME_STAMP BETWEEN FROM_UNIXTIME(" + ConvertToString(begin_time) + ") AND FROM_UNIXTIME(" + ConvertToString(end_time) + ")"; assert(hasData); // This method should never be called before there is header data try { dbResults = dbIn->Query(sqlString.c_str()); } catch (GATS_Exception ex) { string errStr = string("SofieDBinput::Problem with Sun Sensor data for event") + ConvertToString(header. getEventNumber()) + ", message: " + ex.what(); cerr << errStr << endl; THROW_GATS_EXCEPTION(IOException, errStr); } if(dbResults.size() < 1) { string errStr = string("getSunSensorData::No data found for event ") + ConvertToString(header. getEventNumber()); cerr << errStr << endl; THROW_GATS_EXCEPTION(IOException, errStr); } for(unsigned long j = 0; j < dbResults.size(); j++) { int i = 0; time = dbResults[j][i++].asLong(); msec = dbResults[j][i++].asLong(); X_Low = dbResults[j][i++].asInt(); X_High = dbResults[j][i++].asLong(); Y_Low = dbResults[j][i++].asLong(); Y_High = dbResults[j][i++].asLong(); trackStatus = dbResults[j][i++].asInt(); Elev = dbResults[j][i++].asLong(); Azim = dbResults[j][i++].asLong(); for(unsigned long k = 0; k < Sums.size(); k++) { Sums[k] = dbResults[j][i++].asLong(); } sampletime = 1.*time + msec/MICRO_PER_MINUTE; SSSamples.push_back(SunSensorSample(sampletime, X_Low, X_High, Y_Low, Y_High, Elev, Azim, trackStatus, Sums)); } return SunSensorData(SSSamples); } /// Returns the filter holder temperature information for the current event /// FilTSignal SofieDBinput::getfilterT() { const unsigned long NUM_OF_FILTER_HOLDERS = 8; double sampletime; long time; long msec; valarray Tem(SOFIE::Num_of_SCMF); // channel values string tableName = dbParam.getHouseKeepingTable(); string version_id = dbParam.getVersionID(); GATS_DB *dbIn = dbParam.getDBConn(); long begin_time = static_cast (header.getEventStart() ); long end_time = static_cast (header.getEventEnd() +0.5); GATS_DB_Results dbResults; deque filterTArray; string sqlString = string("SELECT UNIX_TIMESTAMP(PACKET_DATETIME), PACKET_MILLISECONDS,") + "CSM_FILTER_RETAINER_1_TEMPERATURE, " + "CSM_FILTER_RETAINER_2_TEMPERATURE, " + "CSM_FILTER_RETAINER_3_TEMPERATURE, " + "CSM_FILTER_RETAINER_4_TEMPERATURE, " + "CSM_FILTER_RETAINER_5_TEMPERATURE, " + "CSM_FILTER_RETAINER_6_TEMPERATURE, " + "CSM_FILTER_RETAINER_7_TEMPERATURE, " + "CSM_FILTER_RETAINER_8_TEMPERATURE " + " FROM " + tableName + " WHERE VERSION_ID = '" + version_id + "'" + " AND PACKET_DATETIME BETWEEN FROM_UNIXTIME(" + ConvertToString(begin_time) + ") AND FROM_UNIXTIME(" + ConvertToString(end_time) + ")"; assert(hasData); // This method should never be called before there is header data // cout << "sqlString = " << sqlString << endl << endl; try { dbResults = dbIn->Query(sqlString.c_str()); } catch (GATS_Exception ex) { string errStr = string("SofieDBinput::Problem with filter data for event") + ConvertToString(header. getEventNumber()) + ", message: " + ex.what(); cerr << errStr << endl; THROW_GATS_EXCEPTION(IOException, errStr); } if(dbResults.size() < 1) { string errStr = string("getDBfilT::No data found for event ") + ConvertToString(header. getEventNumber()); cerr << errStr << endl; THROW_GATS_EXCEPTION(IOException, errStr); } for(unsigned long j = 0; j < dbResults.size(); j++) { time = dbResults[j][0].asLong(); msec = dbResults[j][1].asLong(); for(unsigned long k = 0; k < NUM_OF_FILTER_HOLDERS; k++) { Tem[k] = dbResults[j][2+k].asDouble(); } sampletime = time + msec/MICRO_PER_MINUTE; filterTArray.push_back( FilterTSample(sampletime, Tem) ); } return FilTSignal(filterTArray); } /// Returns the detector temperature information for the current event /// DetectorTemperature SofieDBinput::getDetectorT() { double sampletime; long time; long msec; vector Tem; // channel values string tableName = dbParam.getHouseKeepingTable(); string version_id = dbParam.getVersionID(); GATS_DB *dbIn = dbParam.getDBConn(); long begin_time = static_cast (header.getEventStart() ); long end_time = static_cast (header.getEventEnd() +0.5); GATS_DB_Results dbResults; vector detectorTArray; string sqlString = string("SELECT UNIX_TIMESTAMP(PACKET_DATETIME), PACKET_MILLISECONDS,") + "DETECTOR_1_TEMPERATURE, " + "DETECTOR_2_TEMPERATURE, " + "DETECTOR_3_TEMPERATURE, " + "DETECTOR_4_TEMPERATURE, " + "DETECTOR_5_TEMPERATURE, " + "DETECTOR_6_TEMPERATURE, " + "DETECTOR_7_TEMPERATURE, " + "DETECTOR_8_TEMPERATURE, " + "DETECTOR_9_TEMPERATURE, " + "DETECTOR_10_TEMPERATURE, " + "DETECTOR_11_TEMPERATURE, " + "DETECTOR_12_TEMPERATURE, " + "DETECTOR_13_TEMPERATURE, " + "DETECTOR_14_TEMPERATURE, " + "DETECTOR_15_TEMPERATURE, " + "DETECTOR_16_TEMPERATURE " + " FROM " + tableName + " WHERE VERSION_ID = '" + version_id + "'" + " AND PACKET_DATETIME BETWEEN FROM_UNIXTIME(" + ConvertToString(begin_time) + ") AND FROM_UNIXTIME(" + ConvertToString(end_time) + ")"; assert(hasData); // This method should never be called before there is header data // cout << "sqlString = " << sqlString << endl << endl; try { dbResults = dbIn->Query(sqlString.c_str()); } catch (exception &ex) { string errStr = string("SofieDBinput::Problem with detector temperature data for event") + ConvertToString(header. getEventNumber()) + ", message: " + ex.what(); cerr << errStr << endl; throw runtime_error(errStr); } if(dbResults.size() < 1) { string errStr = string("getDetectorT::No data found for event ") + ConvertToString(header. getEventNumber()); cerr << errStr << endl; throw runtime_error(errStr); } for(unsigned long j = 0; j < dbResults.size(); j++) { time = dbResults[j][0].asLong(); msec = dbResults[j][1].asLong(); if (dbResults[j].size() != SOFIE::no_of_detectors + 2) { string errStr = string("getDetectorT::wrong number of temperature values retrieved ") + ConvertToString(header. getEventNumber()); cerr << errStr << endl; throw runtime_error(errStr); } for(unsigned long k = 0; k < SOFIE::no_of_detectors; k++) // See if there is a way to actually get length { Tem.push_back(dbResults[j][2+k].asDouble() ); } sampletime = time + msec/MICRO_PER_MINUTE; detectorTArray.push_back( DetectorTSample(sampletime, Tem) ); Tem.clear(); } return DetectorTemperature(detectorTArray); } /// Returns the detector signals for the current event /// DetectorSignals SofieDBinput::getDetectorSignals() { double sampletime; long time; long msec; DetectorSample Asample; stringstream StrBuf; string strLine; string strMsg; deque detectorSamples; string tableName = dbParam.getSignalTable(); string version_id = dbParam.getVersionID(); GATS_DB *dbIn = dbParam.getDBConn(); long begin_time = static_cast (header.getEventStart() ); long end_time = static_cast (header.getEventEnd() + 0.5); GATS_DB_Results dbResults; string sqlString = string("SELECT UNIX_TIMESTAMP(DETECTOR_TIME_STAMP), ") + "SAMPLE_MICROSECONDS," + "DETECTOR_1, " + "DETECTOR_2, " + "DETECTOR_3, " + "DETECTOR_4, " + "DETECTOR_5, " + "DETECTOR_6, " + "DETECTOR_7, " + "DETECTOR_8, " + "DETECTOR_9, " + "DETECTOR_10, " + "DETECTOR_11, " + "DETECTOR_12, " + "DETECTOR_13, " + "DETECTOR_14, " + "DETECTOR_15, " + "DETECTOR_16, " + "DIFFERENCE_1_2, " + "DIFFERENCE_3_4, " + "DIFFERENCE_5_6, " + "DIFFERENCE_7_8, " + "DIFFERENCE_9_10, " + "DIFFERENCE_11_12, " + "DIFFERENCE_13_14, " + "DIFFERENCE_15_16 " + " FROM " + tableName + " WHERE VERSION_ID = '" + version_id + "'" + " AND DETECTOR_TIME_STAMP BETWEEN FROM_UNIXTIME(" + ConvertToString(begin_time) + ") AND FROM_UNIXTIME(" + ConvertToString(end_time) + ")"; assert(hasData); // This method should never be called before there is header data // cout << "sqlString = " << sqlString << endl; try { dbResults = dbIn->Query(sqlString.c_str()); } catch (GATS_Exception ex) { string errStr = string("SofieDBinput::Problem with Detector data for event") + ConvertToString(header. getEventNumber()) + ", message: " + ex.what(); cerr << errStr << endl; THROW_GATS_EXCEPTION(IOException, errStr); } if(dbResults.size() < 1) { string errStr = string("getDBdetector::No data found for event ") + ConvertToString(header. getEventNumber()); THROW_GATS_EXCEPTION(IOException, errStr); } for(unsigned long j = 0; j < dbResults.size(); j++) { time = dbResults[j][0].asLong(); msec = dbResults[j][1].asLong(); sampletime = time + msec/MICRO_PER_MINUTE; Asample.setTime(sampletime); for(long k = 0; k < no_of_detectors; k++) { Asample.setChan(k, dbResults[j][2+k].asDouble() ); } for(long k = 0; k < no_of_chan_diffs; k++) { Asample.setChan(no_of_detectors + k, dbResults[j][2 + no_of_detectors + k].asDouble() ); } detectorSamples.push_back(Asample); } return DetectorSignals(detectorSamples); } //######################################################### /// Returns the Solar image for this event. Since the data can be in /// one of two states, it is left packed /// //SolImageSignal SofieDBinput::getSolImageSignal() // { // // double sampletime; // long time; // long msec; // // valarray sData(SolarImgSampleSize); // SolImageSample Asample; // stringstream StrBuf; // string strLine; // string strMsg; // // vector solImageSamples; // // string tableName = dbParam.getSolarImageTable(); // string version_id = dbParam.getVersionID(); // GATS_DB *dbIn = dbParam.getDBConn(); // long begin_time = static_cast (header.getEventStart() ); // long end_time = static_cast (header.getEventEnd() + 0.5); // // GATS_DB_Results dbResults; // // string sqlString = string("SELECT UNIX_TIMESTAMP(PIXEL_TIME_STAMP), ") + // "SAMPLE_MICROSECONDS," + // "LOW_X_SUM_1, " + // "LOW_X_SUM_2, " + // "LOW_X_SUM_3, " + // "LOW_X_SUM_4, " + // "LOW_X_SUM_5, " + // "LOW_X_SUM_6, " + // "LOW_X_SUM_7, " + // "HIGH_X_SUM_1, " + // "HIGH_X_SUM_2, " + // "HIGH_X_SUM_3, " + // "HIGH_X_SUM_4, " + // "HIGH_X_SUM_5, " + // "HIGH_X_SUM_6, " + // "HIGH_X_SUM_7, " + // "LOW_Y_SUM_1, " + // "LOW_Y_SUM_2, " + // "LOW_Y_SUM_3, " + // "LOW_Y_SUM_4, " + // "LOW_Y_SUM_5, " + // "HIGH_Y_SUM_1, " + // "HIGH_Y_SUM_2, " + // "HIGH_Y_SUM_3, " + // "HIGH_Y_SUM_4, " + // "HIGH_Y_SUM_5, " + // "CENTER_SUM_1, " + // "CENTER_SUM_2, " + // "CENTER_SUM_3, " + // "CENTER_SUM_4, " + // "CENTER_SUM_5, " + // "CENTER_SUM_6, " + // "CENTER_SUM_7 " + // " FROM " + tableName + // " WHERE VERSION_ID = '" + version_id + "'" + // " AND PIXEL_TIME_STAMP BETWEEN FROM_UNIXTIME(" + ConvertToString(begin_time) + // ") AND FROM_UNIXTIME(" + ConvertToString(end_time) + ")"; // // assert(hasData); // This method should never be called before there is header data // //// cout << "sqlString = " << sqlString << endl; // // try { // dbResults = dbIn->Query(sqlString.c_str()); // } // catch (GATS_Exception ex) { // // string errStr = string("SofieDBinput::Problem with Solar Image data for event") + // ConvertToString(header. getEventNumber()) + ", message: " + ex.what(); // cerr << errStr << endl; // THROW_GATS_EXCEPTION(IOException, errStr); // } // // if(dbResults.size() < 1) // { // string errStr = string("getDBdetector::No data found for event ") + // ConvertToString(header. getEventNumber()); // THROW_GATS_EXCEPTION(IOException, errStr); // } // // for(unsigned long j = 0; j < dbResults.size(); j++) // { // time = dbResults[j][0].asLong(); // msec = dbResults[j][1].asLong(); // // sampletime = time + msec/MICRO_PER_MINUTE; // // for(unsigned long k = 0; k < sData.size(); k++) // { //// cout << "dbResults[" << j << "][2+" << k << "].asLong() = " << dbResults[j][2+k].asLong() << endl; // sData[k] = dbResults[j][2+k].asLong(); // } // // Asample = SolImageSample(sampletime, sData); // solImageSamples.push_back(Asample); // } // // return SolImageSignal(solImageSamples); // // } DetectorAtten SofieDBinput::getAttenuation() { // double sampletime; long detector; // long attenuation; DetectorAtten detAtten(SOFIE::no_of_detectors); stringstream StrBuf; string strLine; string strMsg; string errStr; // vector solImageSamples; int event = header.getEventNumber(); string ancillarytableName = dbParam.getSofieSummaryTable();; string tagTableName = dbParam.getEventTagsTable(); string version_id = dbParam.getVersionID(); GATS_DB *dbIn = dbParam.getDBConn(); long begin_time = static_cast (header.getEventStart() ); long end_time = static_cast (header.getEventEnd() + 0.5); GATS_DB_Results dbResults; string sqlString = string("SELECT B.PARAM1, B.PARAM2 FROM ") + ancillarytableName + string(" A, ") + tagTableName + string(" B WHERE A.VERSION_ID = B.VERSION_ID AND B.VERSION_ID = '") + version_id + string("' AND B.TIME BETWEEN FROM_UNIXTIME(") + ConvertToString(begin_time) + string(") AND FROM_UNIXTIME(") + ConvertToString(end_time) + string(") AND A.EVENT_NUMBER = ") + ConvertToString(event) + string(" AND B.TAG_TYPE = 'Balance'"); assert(hasData); // This method should never be called before there is header data // cout << "sqlString = " << sqlString << endl; try { dbResults = dbIn->Query(sqlString.c_str()); } catch (GATS_Exception &ex) { errStr = string("SofieDBinput::getAtten() Problem with Attenuator data for event") + ConvertToString(event) + ", message: " + ex.what(); THROW_GATS_EXCEPTION(IOException, errStr); } if(dbResults.size() < 1) { errStr = string("getDBdetector::getAtten() No data found for event ") + ConvertToString(event); THROW_GATS_EXCEPTION(IOException, errStr); } for(unsigned long j = 0; j < dbResults.size(); j++) try { detector = dbResults[j][0].asLong(); detAtten[detector - 1] = dbResults[j][1].asDouble(); // adjust for 0 based array definitions } catch (exception &ex) { errStr = string("SofieDBinput::getAtten() Indexing problem for detector ") + ConvertToString(detector) + string(", message: ") + ex.what(); throw runtime_error(errStr); } return detAtten; } /* this function no longer reads from the balance_time table. It instead reads the balance begin time and end time from the ancillary tables. Since this now absolute time rather than elapsed time since the beginning of the event, it was necessary to subtract off the event start time in Level0Data input.. LED 06/30/2010 */ BalanceTimes SofieDBinput::getBalanceTimes() { stringstream StrBuf; string strLine; string strMsg; string errStr; double startTime = 0.; double endTime = 0.; int event = header.getEventNumber(); string ancillarytableName = dbParam.getSofieSummaryTable();; // string balTableName = dbParam.getBalanceTimesTable(); string version_id = dbParam.getVersionID(); GATS_DB *dbIn = dbParam.getDBConn(); GATS_DB_Results dbResults; // Balance is now moved to the Event ancillary table as an absolute time... string sqlString = string("SELECT UNIX_TIMESTAMP(BAL_START_TIME), UNIX_TIMESTAMP(BAL_END_TIME) FROM ") + ancillarytableName + string(" WHERE EVENT_NUMBER = ") + ConvertToString(event) + string(" AND VERSION_ID = '") + version_id + string("'"); /* string sqlString = string("SELECT B.balance_start, B.balance_end FROM ") + ancillarytableName + string(" A, ") + balTableName + string(" B WHERE A.TABLE_NUMBER = B.table_number ") + string(" AND A.EVENT_NUMBER = ") + ConvertToString(event) + string(" AND A.VERSION_ID = '") + version_id + string("'"); */ assert(hasData); // This method should never be called before there is header data // cout << "getBalanceTimes() sqlString = " << sqlString << endl; try { dbResults = dbIn->Query(sqlString.c_str()); } catch (GATS_Exception &ex) { errStr = string("SofieDBinput::getBalanceTimes() Problem with times for event") + ConvertToString(event) + ", message: " + ex.what(); THROW_GATS_EXCEPTION(IOException, errStr); } if(dbResults.size() < 1) { errStr = string("SofieDBinput::getBalanceTimes() No data found for event ") + ConvertToString(event); THROW_GATS_EXCEPTION(IOException, errStr); } try { startTime = dbResults[0][0].asLong(); endTime = dbResults[0][1].asLong(); } catch (exception &ex) { errStr = string("SofieDBinput::getBalanceTimes() Problem with data ") + string(", message: ") + ex.what(); throw runtime_error(errStr); } return BalanceTimes(startTime, endTime); }