/* * Pusher.h * * Created on: Dec 10, 2012 * Author: f.casimir */ #ifndef PUSHER_H_ #define PUSHER_H_ #include #include "ParamData.hh" #include "DD.hh" namespace AMDA { namespace Parameters { namespace Base { /** * @class Pusher * @details This class is the operation responsible to transform raw data from DDServer into a ParamData * of the corresponding type ( scalar or vector or Tab2D of short or int or float or double or ... type). */ struct Pusher { Pusher (int maxDim1Size=1,int maxDim2Size=1) : _maxDim1Size(maxDim1Size), _maxDim2Size(maxDim2Size), _paramData(NULL), _fillValue(NAN), _timeRestriction(NAN) {} virtual ~Pusher() {} virtual void put(DD_data_t *data, DD_data_t *timeData) = 0; virtual void putNaN() = 0; void setFillValue(double pFillValue) { _fillValue = pFillValue; } double getFillValue() { return _fillValue; } void setTimeRestriction(double timeRestriction) { _timeRestriction = timeRestriction; } double getTimeRestriction() { return _timeRestriction; } double getTimeByIndex(DD_data_t* data, int index) { if (index >= data->VarNumber) { BOOST_THROW_EXCEPTION(AMDA::AMDA_exception() << AMDA::ex_msg("Try to access to a time outside of the available range")); } if (data->type == DD_CHAR) { return DD_Time2Double((char *) data->Variables[index]); } else if (data->type == DD_DOUBLE) { return *((double*)data->Variables[index]); } else { BOOST_THROW_EXCEPTION(AMDA::AMDA_exception() << AMDA::ex_msg("Unknown time type")); } return 0.; } int _maxDim1Size; /*!< Used for vector and Tab2D */ int _maxDim2Size; /*!< Used for Tab2D */ ParamData* _paramData; /*!< return ParamData to a Process*/ protected: float _fillValue; /*!< When this value is different of NAN, into the raw data, it is replaced by NAN into ParamData. */ double _timeRestriction; }; } //#define DD_SHORT 4 //#define DD_INT 1 //#define DD_FLOAT 2 //#define DD_DOUBLE 3 //#define DD_CHAR 0 typedef enum { CT_UNKNOWN, CT_SCALAR, CT_TAB1D, CT_TAB2D } ContainerType; template struct MapType { typedef void Type; }; template <> struct MapType<4> { typedef short Type; }; template <> struct MapType<1> { typedef int Type; }; template <> struct MapType<2> { typedef float Type; }; template <> struct MapType<3> { typedef double Type; }; template <> struct MapType<0> { typedef char Type; }; template class Pusher; /** * @brief Pusher implementation for the CT_TAB2D. */ template class Pusher : public Base::Pusher { public: typedef typename MapType::Type BaseElemenType; typedef Tab2DData ElemenType; typedef ParamDataSpec SpecParamData; SpecParamData* _specParamData; Pusher(int maxDim1Size, int maxDim2Size, int maxDim3Size, int dim1Num = 0, int dim2Num = 1, int dim3Num = -1, int dim3CutIndex = -1, int minSumIndex=-1, int maxSumIndex=-1) : Base::Pusher(maxDim1Size,maxDim2Size), _maxDim3Size(maxDim3Size), _dim1Num(dim1Num), _dim2Num(dim2Num), _dim3Num(dim3Num), _dim3CutIndex(dim3CutIndex),_minSumIndex(minSumIndex), _maxSumIndex(maxSumIndex) { _paramData = _specParamData = createParamData(); } void put(DD_data_t *data, DD_data_t *timeData) { BaseElemenType **lData = reinterpret_cast(data->Variables); //ParamData is created, add data _specParamData->getDataList().resize(data->VarNumber); if(_dim3CutIndex == -1 && _minSumIndex != -1 && _maxSumIndex != -1){ for (int index = 0; index < data->VarNumber; index++) { double t = getTimeByIndex(timeData, index); _paramData->getTimeList().push_back(t); if ((getTimeRestriction() > 0) && !isnan(getTimeRestriction())) { if (t >= getTimeRestriction()) { putNaN(); continue; } } ElemenType elem = ElemenType(_maxDim1Size,_maxDim2Size); elem << NotANumber(); for (int dim1Index= 0; dim1Index < data->Dimensions[_dim1Num]; ++dim1Index) { for (int dim2Index= 0; dim2Index < data->Dimensions[_dim2Num]; ++dim2Index) { BaseElemenType cumulatedElement; cumulatedElement << NotANumber() ; for(int sumIndex=_minSumIndex; sumIndex <= _maxSumIndex; ++sumIndex){ int dataIndex = 0; if (_dim3Num >= 0 && _dim3Num < 3 && data->DimNumber == 3) { int curentIndex = (sumIndex >= 0 && sumIndex < data->Dimensions[_dim3Num]) ? sumIndex : 0; if (_dim3Num == 0) { dataIndex = curentIndex*data->Dimensions[_dim1Num]*data->Dimensions[_dim2Num] + dim1Index*data->Dimensions[_dim2Num] + dim2Index; } else if (_dim3Num == 1) { dataIndex = dim1Index*data->Dimensions[_dim2Num]*data->Dimensions[_dim3Num] + curentIndex*data->Dimensions[_dim2Num] + dim2Index; } else { dataIndex = dim1Index*data->Dimensions[_dim2Num]*data->Dimensions[_dim3Num] + dim2Index*data->Dimensions[_dim3Num] + curentIndex; } } else { dataIndex = dim1Index*data->Dimensions[_dim2Num]+dim2Index; } BaseElemenType baseElem = lData[index][dataIndex]; if (!isnan(_fillValue)) { double crt_val = baseElem; bool is_fill_value = isApproximatelyEqual(crt_val, _fillValue); if(is_fill_value) baseElem << NotANumber(); } if (!isNAN(baseElem)) { if (isNAN(cumulatedElement)) cumulatedElement << ElemNull(); cumulatedElement += baseElem; } } elem[dim1Index][dim2Index] = cumulatedElement; } } _specParamData->getDataList().push_back(elem); } }else{ for (int index = 0; index < data->VarNumber; index++) { double t = getTimeByIndex(timeData, index); _paramData->getTimeList().push_back(t); if ((getTimeRestriction() > 0) && !isnan(getTimeRestriction())) { if (getTimeByIndex(data, index) >= getTimeRestriction()) { putNaN(); continue; } } ElemenType elem = ElemenType(_maxDim1Size,_maxDim2Size); elem << NotANumber(); for (int dim1Index= 0; dim1Index < data->Dimensions[_dim1Num]; ++dim1Index) { for (int dim2Index= 0; dim2Index < data->Dimensions[_dim2Num]; ++dim2Index) { int dataIndex = 0; if (_dim3Num >= 0 && _dim3Num < 3 && data->DimNumber == 3) { int cutIndex = (_dim3CutIndex >= 0 && _dim3CutIndex < data->Dimensions[_dim3Num]) ? _dim3CutIndex : 0; if (_dim3Num == 0) { dataIndex = cutIndex*data->Dimensions[_dim1Num]*data->Dimensions[_dim2Num] + dim1Index*data->Dimensions[_dim2Num] + dim2Index; } else if (_dim3Num == 1) { dataIndex = dim1Index*data->Dimensions[_dim2Num]*data->Dimensions[_dim3Num] + cutIndex*data->Dimensions[_dim2Num] + dim2Index; } else { dataIndex = dim1Index*data->Dimensions[_dim2Num]*data->Dimensions[_dim3Num] + dim2Index*data->Dimensions[_dim3Num] + cutIndex; } } else { dataIndex = dim1Index*data->Dimensions[_dim2Num]+dim2Index; } BaseElemenType baseElem = lData[index][dataIndex]; if (!isnan(_fillValue)) { double crt_val = baseElem; bool is_fill_value = isApproximatelyEqual(crt_val, _fillValue); if(is_fill_value) baseElem << NotANumber(); } elem[dim1Index][dim2Index] = baseElem; } } _specParamData->getDataList().push_back(elem); } } } void putNaN() { _specParamData->getDataList().resize(1); ElemenType nanElem = ElemenType(_maxDim1Size,_maxDim2Size); for(int i = 0; i < _maxDim1Size; ++i) { for(int j = 0; j < _maxDim2Size; ++j) { nanElem[i][j] << NotANumber(); } } _specParamData->getDataList().push_back(nanElem); } SpecParamData* createParamData() { return new ParamDataSpec< Tab2DData::Type> >(_maxDim1Size,_maxDim2Size); } private: int _maxDim3Size; int _dim1Num; int _dim2Num; int _dim3Num; int _dim3CutIndex; int _minSumIndex; int _maxSumIndex; }; /** * @brief Pusher implementation for the CT_TAB1D. */ template class Pusher : public Base::Pusher { public: typedef typename MapType::Type BaseElemenType; typedef std::vector ElemenType; typedef ParamDataSpec SpecParamData; SpecParamData* _specParamData; Pusher(int maxDimSize) : Base::Pusher(maxDimSize) { _paramData = _specParamData = createParamData(); } void put(DD_data_t *data, DD_data_t *timeData) { BaseElemenType **lData = reinterpret_cast(data->Variables); //ParamData is created, add data _specParamData->getDataList().resize(data->VarNumber); for (int index = 0; index < data->VarNumber; index++) { double t = getTimeByIndex(timeData, index); _paramData->getTimeList().push_back(t); if ((getTimeRestriction() > 0) && !isnan(getTimeRestriction())) { if (t >= getTimeRestriction()) { putNaN(); continue; } } ElemenType elem = ElemenType(); elem.resize(_maxDim1Size); elem << NotANumber(); std::copy (lData[index], lData[index] + data->Dimensions[0], elem.begin()); if(!isnan(_fillValue)) { for(auto it = elem.begin(); it != elem.end(); ++it) { double crt_val = *it; bool is_fill_value = isApproximatelyEqual(crt_val, _fillValue); if(is_fill_value) { *it << NotANumber(); } } } _specParamData->getDataList().push_back(elem); } } void putNaN() { _specParamData->getDataList().resize(1); ElemenType nanElem = ElemenType(); nanElem.resize(_maxDim1Size); nanElem << NotANumber(); _specParamData->getDataList().push_back(nanElem); } SpecParamData* createParamData() { return new ParamDataSpec< std::vector::Type> >(_maxDim1Size); } }; /** * @brief Pusher implementation for the scalar. */ template class Pusher : public Base::Pusher { public: typedef typename MapType::Type BaseElemenType; typedef BaseElemenType ElemenType; typedef ParamDataSpec SpecParamData; SpecParamData* _specParamData; /** * @brief Constructor * @details Create the real ParamData. */ Pusher() : Base::Pusher() { _paramData = _specParamData = createParamData(); } void put(DD_data_t *data, DD_data_t *timeData) { BaseElemenType **lData = reinterpret_cast(data->Variables); //ParamData is created, add data _specParamData->getDataList().resize(data->VarNumber); BaseElemenType nanElem; nanElem << NotANumber(); if(!isnan(_fillValue)) { BaseElemenType nanElem; nanElem << NotANumber(); for (int index = 0; index < data->VarNumber; index++) { double t = getTimeByIndex(timeData, index); _paramData->getTimeList().push_back(t); if ((getTimeRestriction() > 0) && !isnan(getTimeRestriction())) { if (t >= getTimeRestriction()) { putNaN(); continue; } } double crt_val = *lData[index]; bool is_fill_value = isApproximatelyEqual(crt_val, _fillValue); if(!is_fill_value) { _specParamData->getDataList().push_back(*lData[index]); } else { _specParamData->getDataList().push_back(nanElem); } } } else { for (int index = 0; index < data->VarNumber; index++) { double t = getTimeByIndex(timeData, index); _paramData->getTimeList().push_back(t); if ((getTimeRestriction() > 0) && !isnan(getTimeRestriction())) { if (t >= getTimeRestriction()) { putNaN(); continue; } } _specParamData->getDataList().push_back(*lData[index]); } } } void putNaN() { BaseElemenType nanElem; nanElem << NotANumber(); _specParamData->getDataList().resize(1); _specParamData->getDataList().push_back(nanElem); } SpecParamData* createParamData() { return new SpecParamData(); } }; } /* namespace Parameters */ } /* namespace AMDA */ #endif /* PUSHER_H_ */