Files
front_linux/LFtid1056/pqdif/include/rec_observ.cpp

1861 lines
50 KiB
C++
Raw Normal View History

/*
** CPQDIF_R_Observation class. Implements a PQDIF record "wrapper" for the
** data source record. You can NOT cast a standard record object to this
** class, because it has its own member data.
** --------------------------------------------------------------------------
**
** File name: $Workfile: rec_observ.cpp $
** Last modified: $Modtime: 12/01/00 12:45p $
** Last modified by: $Author: Bill $
**
** VCS archive path: $Archive: /Hank/DMM/FirmWare/Level3/ObDatMgr/rec_observ.cpp $
** VCS revision: $Revision: 30 $
*/
#include "PQDIF_classes.h"
// Local functions
// ===============
// Function to round second values to the nearest nanosecond.
inline double _FixSeconds(double dTime)
{
return floor( dTime * 1000000000.0 + 0.5 )/ 1000000000.0;
}
static void _AddSeconds( TIMESTAMPPQDIF &dt, double secondsToAdd )
{
// Record the current day for an overflow check.
DWORD dwDay = dt.day;
// Perform the requested operation.
dt.sec += secondsToAdd;
// If the result is greater than the number of seconds in
// a day then ...
if( dt.sec > (double) SECONDS_PER_DAY )
{
// Carry resulting number of days.
long lDays = (long)( dt.sec / (double) SECONDS_PER_DAY );
dt.day += lDays;
dt.sec -= ( lDays * (double) SECONDS_PER_DAY );
// Check for an overflow.
if( dt.day < dwDay )
{
dt.day = 0xffffffff;
dt.sec = 86399.999999;
}
}
// Else if the result is less than 0.0.
else if( dt.sec < 0.0 )
{
// Borrow the required number of days.
long lDays = 1 - (long)( dt.sec / (double) SECONDS_PER_DAY );
dt.day -= lDays;
dt.sec += ( lDays * (double) SECONDS_PER_DAY );
// Check for an underflow.
if( dt.day > dwDay )
{
dt.day = 0;
dt.sec = 0.0;
}
}
// Adjust the result.
dt.sec = _FixSeconds( dt.sec );
}
// Construction
// ============
CPQDIF_R_Observation::CPQDIF_R_Observation()
{
m_pds = NULL;
m_psett = NULL;
m_record = NULL;
}
CPQDIF_R_Observation::CPQDIF_R_Observation( CPQDIFRecord& record )
{
m_pds = NULL;
m_psett = NULL;
m_record = (CPQDIF_R_General *) &record;
}
CPQDIF_R_Observation::~CPQDIF_R_Observation()
{
// Don't destroy m_pds or m_record; these are only by reference, not by value.
}
bool CPQDIF_R_Observation::GetInfo
(
TIMESTAMPPQDIF& timeStart,
TIMESTAMPPQDIF& timeCreate,
string& name
)
{
bool status;
long countEntries = 0;
CPQDIF_E_Scalar * psc;
CPQDIF_E_Vector * pvect;
// Init
status = TRUE;
memset( &timeStart, 0, sizeof( timeStart ) );
memset( &timeCreate, 0, sizeof( timeCreate ) );
name = "";
// First, find the times
if( status )
{
psc = FindScalarInCollection( m_record->m_pcollMain, tagTimeStart );
if( psc )
{
status = psc->GetValueTimeStamp( timeStart );
}
}
if( status )
{
psc = FindScalarInCollection( m_record->m_pcollMain, tagTimeCreate );
if( psc )
{
status = psc->GetValueTimeStamp( timeCreate );
}
}
// Get name
if( status )
{
pvect = FindVectorInCollection( m_record->m_pcollMain, tagObservationName );
if( pvect )
{
status = pvect->GetValues( name );
}
}
return status;
}
long CPQDIF_R_Observation::GetCountChannels( void )
{
long count = 0;
CPQDIF_E_Collection * pcolCI;
pcolCI = GetChannelInstances();
if( pcolCI )
{
count = pcolCI->GetCount();
}
return count;
}
bool CPQDIF_R_Observation::GetTriggerInfo
(
UINT4& idTriggerMethod,
CPQDIF_E_Vector ** pvectTriggerChanIdx,
TIMESTAMPPQDIF& timeTriggered
)
{
bool status = false;
long countEntries = 0;
CPQDIF_E_Scalar * psc;
CPQDIF_E_Vector * pvect;
// Init
idTriggerMethod = ID_TRIGGER_METH_NONE;
//ASSERT( pvectTriggerChanIdx );
*pvectTriggerChanIdx = NULL;
memset( &timeTriggered, 0, sizeof( timeTriggered ) );
// First, find the trigger method
psc = FindScalarInCollection( m_record->m_pcollMain, tagTriggerMethodID );
if( psc )
{
status = psc->GetValueUINT4( idTriggerMethod );
}
else
{
// Default to channel? NAHHH
//status = TRUE;
//idTriggerMethod = ID_TRIGGER_METH_CHANNEL;
}
// Get triggered channels? (NOT required; leave status alone)
if( status && idTriggerMethod == ID_TRIGGER_METH_CHANNEL )
{
pvect = FindVectorInCollection( m_record->m_pcollMain, tagChannelTriggerIdx );
if( pvect )
{
// Validate physical type
if( pvect->GetPhysicalType() == ID_PHYS_TYPE_UNS_INTEGER4 )
{
// Return a pointer to the vector
*pvectTriggerChanIdx = pvect;
}
}
}
// Get the time it was triggered
if( status )
{
status = false;
psc = FindScalarInCollection( m_record->m_pcollMain, tagTimeTriggered );
if( psc )
{
status = psc->GetValueTimeStamp( timeTriggered );
}
}
return status;
}
long CPQDIF_R_Observation::GetCountSeries( int idxChannel )
{
long count = 0;
CPQDIF_E_Collection * pcolOneChannel;
CPQDIF_E_Collection * pcolSI;
pcolOneChannel = GetOneChannel( idxChannel );
if( pcolOneChannel )
{
pcolSI = GetSeriesInstances( pcolOneChannel );
if( pcolSI )
{
count = pcolSI->GetCount();
}
}
return count;
}
bool CPQDIF_R_Observation::GetChannelInfo
(
long idxChannel,
string& name,
UINT4& idPhase,
GUID& idQuantityType,
UINT4& idQuantityMeasured
)
{
bool status = true;
long idxChannelDefn;
// Find the channel defn index
if( status )
{
status = GetChannelDefnIdx( idxChannel, idxChannelDefn );
}
// Gather information from the channel definitions
if( status && m_pds )
{
status = m_pds->GetChannelDefnInfo( idxChannelDefn, name, idPhase,
idQuantityType, idQuantityMeasured );
}
else
{
status = false;
}
return status;
}
bool CPQDIF_R_Observation::GetChannelPrimarySeries
(
long idxChannel,
long& idxPrimarySeries
)
{
bool status = true;
long idxChannelDefn;
// Find the channel defn index
if( status )
{
status = GetChannelDefnIdx( idxChannel, idxChannelDefn );
}
// Gather information from the channel definitions
if( status && m_pds )
{
status = m_pds->GetChannelPrimarySeries( idxChannelDefn, idxPrimarySeries );
}
else
{
status = false;
}
return status;
}
#ifdef zap
//
//
// Depricated function
//
bool CPQDIF_R_Observation::GetChannelThresholds
(
long idxChannel,
UINT4& triggerTypeID,
REAL8& fullScale,
REAL8& noiseFloor,
REAL8& triggerLow,
REAL8& triggerHigh,
REAL8& triggerRate,
CPQDIF_E_Vector& triggerShapeParam // Array of [3]
)
{
bool status = false;
long idxChannelDefn;
bool found;
long idxChannSett;
long countChannSett;
UINT4 idxChannelDefnSett;
// DO we have settings?
if( m_psett )
{
// Determine which channel def'n is used for this channel
// Find the channel defn index
status = GetChannelDefnIdx( idxChannel, idxChannelDefn );
// Check all settings channels to see which matches the def'n
if( status )
{
// Init
status = false;
countChannSett = m_psett->GetCountChannels();
for( idxChannSett = 0; idxChannSett < countChannSett; idxChannSett++ )
{
found = m_psett->GetChannelInfo( idxChannSett, idxChannelDefnSett,
triggerTypeID, fullScale, noiseFloor,
triggerLow, triggerHigh, triggerRate,
triggerShapeParam );
// Is this the one that corresponds to the same def'n?
if( found && idxChannelDefn == (long) idxChannelDefnSett )
{
status = TRUE;
break;
}
} // For( channel setting )
} // Found channel def'n
} // Have settings
return status;
}
#endif
bool CPQDIF_R_Observation::GetSeriesInfo
(
long idxChannel,
long idxSeries,
UINT4& idQuantityUnits,
GUID& idQuantityCharacteristic,
GUID& idValueType
)
{
bool status = true;
long idxChannelDefn;
UINT4 idStorageMethod;
// Find the channel defn index
if( status )
{
status = GetChannelDefnIdx( idxChannel, idxChannelDefn );
}
// Gather information from the series definition
if( status && m_pds )
{
status = m_pds->GetSeriesDefnInfo( idxChannelDefn, idxSeries,
idQuantityUnits, idValueType, idQuantityCharacteristic,
idStorageMethod );
}
else
{
status = false;
}
return status;
}
long CPQDIF_R_Observation::AddChannel
(
long idxChannelDefn
)
{
long idxNew = -1;
CPQDIF_E_Collection * pcolInstances = GetChannelInstances();
CPQDIF_E_Collection * pcollOne;
CPQDIF_E_Collection * pcollSeriesInstances;
if( pcolInstances )
{
// Get the new index
idxNew = GetCountChannels();
// Create the new channel instance
pcollOne = (CPQDIF_E_Collection *) theFactory.NewElement( ID_ELEMENT_TYPE_COLLECTION );
pcollOne->SetTag( tagOneChannelInst );
// Stuff in the information...
pcollOne->SetScalarUINT4( tagChannelDefnIdx, idxChannelDefn );
// Also need a series instances collection
pcollSeriesInstances = (CPQDIF_E_Collection *) theFactory.NewElement( ID_ELEMENT_TYPE_COLLECTION );
if( pcollSeriesInstances )
{
pcollSeriesInstances->SetTag( tagSeriesInstances );
pcollOne->Add( pcollSeriesInstances );
}
// Add it!
pcolInstances->Add( pcollOne );
}
return idxNew;
}
long CPQDIF_R_Observation::AddSeriesDouble
(
long idxChannel,
long countValues,
double * arValues
)
{
long idxNew = -1;
CPQDIF_E_Vector * pvectData;
long idx;
double * pValue;
// Create vector for the series data
pvectData = (CPQDIF_E_Vector *) theFactory.NewElement( ID_ELEMENT_TYPE_VECTOR );
if( pvectData )
{
pvectData->SetTag( tagSeriesValues );
pvectData->SetPhysicalType( ID_PHYS_TYPE_REAL8 );
// Copy over series data
pValue = arValues;
pvectData->SetCount( countValues );
for( idx = 0; idx < countValues; idx++, pValue++ )
{
pvectData->SetValue( idx, *pValue );
}
// Add it ...
idxNew = AddSeriesVector( idxChannel, pvectData );
// If it was not successful, delete the vector
if( idxNew < 0 )
{
delete pvectData;
}
}
return idxNew;
}
long CPQDIF_R_Observation::AddSeriesVector
(
long idxChannel,
CPQDIF_E_Vector * pvectData
)
{
long idxNew = -1;
CPQDIF_E_Collection * pcolOneChannel;
CPQDIF_E_Collection * pcolSI;
CPQDIF_E_Collection * pcollOne;
pcolOneChannel = GetOneChannel( idxChannel );
if( pcolOneChannel && pvectData )
{
pcolSI = GetSeriesInstances( pcolOneChannel );
if( pcolSI )
{
// New channel index
idxNew = pcolSI->GetCount();
// Create the new channel def'n
pcollOne = (CPQDIF_E_Collection *) theFactory.NewElement( ID_ELEMENT_TYPE_COLLECTION );
if( pcollOne )
{
// Set the tag for this collection ...
pcollOne->SetTag( tagOneSeriesInstance );
// Make sure the vector has the right tag ...
pvectData->SetTag( tagSeriesValues );
// The vector is currently the only member of this collection.
pcollOne->Add( pvectData );
}
// Add it!
pcolSI->Add( pcollOne );
}
}
return idxNew;
}
long CPQDIF_R_Observation::AddSeriesShared
(
long idxChannel,
long idxChannelShared,
long idxSeriesShared
)
{
long idxNew = -1;
CPQDIF_E_Collection * pcolOneChannel;
CPQDIF_E_Collection * pcolSI;
CPQDIF_E_Collection * pcollOne;
CPQDIF_E_Scalar * pscSharedChannel;
CPQDIF_E_Scalar * pscSharedSeries;
pcolOneChannel = GetOneChannel( idxChannel );
if( pcolOneChannel )
{
pcolSI = GetSeriesInstances( pcolOneChannel );
if( pcolSI )
{
// New channel index
idxNew = pcolSI->GetCount();
// Create the new channel def'n
pcollOne = (CPQDIF_E_Collection *) theFactory.NewElement( ID_ELEMENT_TYPE_COLLECTION );
if( pcollOne )
{
// Set the tag for this collection ...
pcollOne->SetTag( tagOneSeriesInstance );
// Create scalars which indicate which channel/series is to be shared
pscSharedChannel = (CPQDIF_E_Scalar *) theFactory.NewElement( ID_ELEMENT_TYPE_SCALAR );
pscSharedSeries = (CPQDIF_E_Scalar *) theFactory.NewElement( ID_ELEMENT_TYPE_SCALAR );
if( pscSharedChannel && pscSharedSeries )
{
// Tags & values
pscSharedChannel->SetTag( tagSeriesShareChannelIdx );
pscSharedChannel->SetPhysicalType( ID_PHYS_TYPE_UNS_INTEGER4 );
pscSharedChannel->SetValueUINT4( idxChannelShared );
pscSharedSeries->SetTag( tagSeriesShareSeriesIdx );
pscSharedSeries->SetPhysicalType( ID_PHYS_TYPE_UNS_INTEGER4 );
pscSharedSeries->SetValueUINT4( idxSeriesShared );
// Stuff 'em
pcollOne->Add( pscSharedChannel );
pcollOne->Add( pscSharedSeries );
}
}
// Add it!
pcolSI->Add( pcollOne );
}
}
return idxNew;
}
bool CPQDIF_R_Observation::SetSeriesBaseQuantity
(
long idxChannel,
long idxSeries,
double value
)
{
bool status = false;
CPQDIF_E_Collection * pcol;
CPQDIF_E_Scalar * psc;
// Find the series
pcol = GetOneSeries( idxChannel, idxSeries );
if( pcol )
{
psc = FindScalarInCollection( pcol, tagSeriesBaseQuantity );
if( !psc )
{
// Create it !
psc = (CPQDIF_E_Scalar *) theFactory.NewElement( ID_ELEMENT_TYPE_SCALAR );
if( psc )
{
pcol->Add( psc );
}
}
// Init the scalar
if( psc )
{
psc->SetTag( tagSeriesBaseQuantity );
psc->SetValueREAL8( value );
status = TRUE;
}
}
return status;
}
bool CPQDIF_R_Observation::SetSeriesScale
(
long idxChannel,
long idxSeries,
double scale,
double offset
)
{
bool status = false;
CPQDIF_E_Collection * pcol;
CPQDIF_E_Scalar * psc;
#ifdef zap
// Find the series
pcol = GetOneSeries( idxChannel, idxSeries );
if( pcol )
{
psc = FindOrCreateScalarInCollection( pcol, tagSeriesScale, ID_PHYS_TYPE_REAL8 );
if( psc )
{
status = psc->SetValueREAL8( scale );
}
psc = FindOrCreateScalarInCollection( pcol, tagSeriesOffset, ID_PHYS_TYPE_REAL8 );
if( psc )
{
status = psc->SetValueREAL8( offset );
}
}
#endif
// Find the series
pcol = GetOneSeries( idxChannel, idxSeries );
if( pcol )
{
psc = FindScalarInCollection( pcol, tagSeriesScale );
if( !psc )
{
// Create it !
psc = (CPQDIF_E_Scalar *) theFactory.NewElement( ID_ELEMENT_TYPE_SCALAR );
if( psc )
{
pcol->Add( psc );
}
}
// Init the scalar
if( psc )
{
psc->SetTag( tagSeriesScale );
psc->SetValueREAL8( scale );
status = TRUE;
}
psc = FindScalarInCollection( pcol, tagSeriesOffset );
if( !psc )
{
// Create it !
psc = (CPQDIF_E_Scalar *) theFactory.NewElement( ID_ELEMENT_TYPE_SCALAR );
if( psc )
{
pcol->Add( psc );
}
}
// Init the scalar
if( psc )
{
psc->SetTag( tagSeriesOffset );
psc->SetValueREAL8( offset );
status = TRUE;
}
}
return status;
}
bool CPQDIF_R_Observation::GetSeriesBaseQuantity
(
long idxChannel,
long idxSeries,
double& value
)
{
bool status = false;
CPQDIF_E_Collection * pcol;
CPQDIF_E_Scalar * psc;
// Find the series
pcol = GetOneSeries( idxChannel, idxSeries );
if( pcol )
{
psc = FindScalarInCollection( pcol, tagSeriesBaseQuantity );
if( psc )
{
status = psc->GetValueREAL8( value );
}
}
return status;
}
#ifdef PQDIF_USE_COM
bool CPQDIF_R_Observation::GetObservationExtendedData
(
GUID& gidTag,
VARIANT& value
)
{
bool status = false;
CPQDIF_E_Scalar * psc;
psc = FindScalarInCollection( m_record->m_pcollMain, gidTag );
if( psc )
{
status = psc->GetValue( value );
}
return status;
}
bool CPQDIF_R_Observation::GetSeriesExtendedData
(
long idxChannel,
long idxSeries,
GUID& gidTag,
VARIANT& value
)
{
bool status = false;
CPQDIF_E_Collection * pcollOneChannel;
CPQDIF_E_Scalar * psc;
pcollOneChannel = GetOneSeries( idxChannel, idxSeries );
if (pcollOneChannel)
{
psc = FindScalarInCollection( pcollOneChannel, gidTag );
if( psc )
{
status = psc->GetValue( value );
}
}
return status;
}
bool CPQDIF_R_Observation::GetChannelExtendedData
(
long idxChannel,
GUID& gidTag,
VARIANT& value
)
{
bool status = false;
CPQDIF_E_Collection * pcollOneChannel;
CPQDIF_E_Scalar * psc;
pcollOneChannel = GetOneChannel( idxChannel );
if (pcollOneChannel)
{
psc = FindScalarInCollection( pcollOneChannel, gidTag );
if( psc )
{
status = psc->GetValue( value );
}
}
return status;
}
#endif
bool CPQDIF_R_Observation::GetSeriesDefnNominal
(
long idxChannel,
long idxSeries,
double & dNominal
)
{
bool status = false;
long idxChannelDefn;
status = GetChannelDefnIdx( idxChannel, idxChannelDefn );
if (m_pds)
{
status = m_pds->GetSeriesDefnNominal(idxChannelDefn, idxSeries, dNominal);
}
return status;
}
bool CPQDIF_R_Observation::GetSeriesDefnPrecisionAndResolution
(
long idxChannel,
long idxSeries,
UINT4 & uPrecision,
double & dResolution
)
{
bool status = false;
long idxChannelDefn;
status = GetChannelDefnIdx( idxChannel, idxChannelDefn );
if (m_pds)
{
status = m_pds->GetSeriesDefnPrecisionAndResolution(idxChannelDefn, idxSeries, uPrecision, dResolution);
}
return status;
}
bool CPQDIF_R_Observation::GetSeriesScale
(
long idxChannel,
long idxSeries,
double& scale,
double& offset
)
{
bool status = false;
CPQDIF_E_Collection * pcol;
CPQDIF_E_Scalar * psc;
// Find the series
pcol = GetOneSeries( idxChannel, idxSeries );
if( pcol )
{
psc = FindScalarInCollection( pcol, tagSeriesScale );
if( psc )
{
status = psc->GetValueREAL8( scale );
}
psc = FindScalarInCollection( pcol, tagSeriesOffset );
if( psc )
{
status = psc->GetValueREAL8( offset );
}
}
return status;
}
CPQDIF_E_Vector * CPQDIF_R_Observation::GetSeriesValueVector
(
long idxChannel,
long idxSeries
)
{
CPQDIF_E_Vector * pvectReturn = NULL;
CPQDIF_E_Collection * pcolOneSeries;
pcolOneSeries = GetOneSeries( idxChannel, idxSeries );
if( pcolOneSeries )
{
pvectReturn = FindVectorInCollection( pcolOneSeries, tagSeriesValues );
}
return pvectReturn;
}
bool CPQDIF_R_Observation::SetTimeCreateAndTimeStart
(
const TIMESTAMPPQDIF& timeCreate,
const TIMESTAMPPQDIF& timeStart
)
{
bool status = false;
CPQDIF_E_Scalar * psc;
CPQDIF_E_Vector * pvect;
// Init
//ASSERT(aidxTriggerChan);
// First, find (or create) the trigger method
psc = FindOrCreateScalarInCollection(m_record->m_pcollMain,
tagTimeCreate, ID_PHYS_TYPE_TIMESTAMPPQDIF);
// Set its value
if (psc)
{
status = psc->SetValueTimeStamp(timeCreate);
}
// Set the time it was triggered
if (status)
{
status = false;
psc = FindOrCreateScalarInCollection(m_record->m_pcollMain,
tagTimeStart, ID_PHYS_TYPE_TIMESTAMPPQDIF);
// Set value
if (psc)
{
status = psc->SetValueTimeStamp(timeStart);
}
}
return status;
}
bool CPQDIF_R_Observation::SetTriggerInfo
(
UINT4 idTriggerMethod,
long countTriggers,
const UINT4 * aidxTriggerChan,
const TIMESTAMPPQDIF& timeTriggered
)
{
bool status = false;
CPQDIF_E_Scalar * psc;
CPQDIF_E_Vector * pvect;
// Init
//ASSERT( aidxTriggerChan );
// First, find (or create) the trigger method
psc = FindOrCreateScalarInCollection( m_record->m_pcollMain,
tagTriggerMethodID, ID_PHYS_TYPE_UNS_INTEGER4 );
// Set its value
if( psc )
{
status = psc->SetValueUINT4( idTriggerMethod );
}
// Get triggered channels?
if( status && idTriggerMethod == ID_TRIGGER_METH_CHANNEL )
{
status = false;
pvect = FindOrCreateVectorInCollection( m_record->m_pcollMain,
tagChannelTriggerIdx, ID_PHYS_TYPE_UNS_INTEGER4 );
// Set its value(s)
if( pvect )
{
// Validate physical type
if( pvect->GetPhysicalType() == ID_PHYS_TYPE_UNS_INTEGER4 )
{
pvect->SetCount( countTriggers );
for( long idx = 0; idx < countTriggers; idx++ )
{
pvect->SetValueUINT4( idx, aidxTriggerChan[ idx ] );
}
status = TRUE;
}
}
}
// Set the time it was triggered
if( status )
{
status = false;
psc = FindOrCreateScalarInCollection( m_record->m_pcollMain,
tagTimeTriggered, ID_PHYS_TYPE_TIMESTAMPPQDIF );
// Set value
if( psc )
{
status = psc->SetValueTimeStamp( timeTriggered );
}
}
return status;
}
long CPQDIF_R_Observation::GetCountResolvedSeries
(
long idxChannel,
long idxSeries,
bool noShare
)
{
int idx;
bool status = false;
long countPoints = 0;
long idxChannelDefn;
UINT4 idQuantityUnits;
GUID idQuantityCharacteristic;
GUID idValueType;
UINT4 idStorageMethod;
bool gotShareChannel = false;
bool gotShareSeries = false;
UINT4 idxShareChannelIdx = 0;
UINT4 idxShareSeriesIdx = 0;
CPQDIF_Element * pel = NULL;
CPQDIF_E_Collection * pcol = NULL;
CPQDIF_E_Vector * pvectSeriesArray = NULL;
// Verify that we're in an observation record
// Requires a data source record
if( m_record && m_pds && idxChannel >= 0 && idxSeries >= 0)
{
// Find the channel defn index
status = GetChannelDefnIdx( idxChannel, idxChannelDefn );
// Fail if we got a bogus index
if( status && idxChannelDefn < 0 )
status = false;
}
// Get the storage method
if( status )
{
status = m_pds->GetSeriesDefnInfo( idxChannelDefn, idxSeries,
idQuantityUnits, idValueType, idQuantityCharacteristic, idStorageMethod );
}
// Look for shared channel and series indices, or a vector of values
if( status )
{
// Find the series
pcol = GetOneSeries( idxChannel, idxSeries );
if( pcol )
{
status = true;
for( idx = 0; idx < pcol->GetCount(); idx++ )
{
pel = pcol->GetElement( idx );
if( pel )
{
if( pel->GetElementType() == ID_ELEMENT_TYPE_SCALAR )
{
CPQDIF_E_Scalar *psc = (CPQDIF_E_Scalar *) pel;
if( PQDIF_IsEqualGUID( pel->GetTag(), tagSeriesShareChannelIdx ) )
{
gotShareChannel = TRUE;
psc->GetValueUINT4( idxShareChannelIdx );
if( gotShareSeries )
break;
}
if( PQDIF_IsEqualGUID( pel->GetTag(), tagSeriesShareSeriesIdx ) )
{
gotShareSeries = TRUE;
psc->GetValueUINT4( idxShareSeriesIdx );
if( gotShareChannel )
break;
}
}
else if( pel->GetElementType() == ID_ELEMENT_TYPE_VECTOR
&& PQDIF_IsEqualGUID( pel->GetTag(), tagSeriesValues ) )
{
pvectSeriesArray = (CPQDIF_E_Vector *) pel;
break;
}
}
}
}
}
// Now count the values
if( status )
{
if( gotShareChannel && gotShareSeries )
{
// We're sharing the series from somwhere else --
// generate it from the shared indices
if( !noShare )
{
countPoints = GetCountResolvedSeries(
(long) idxShareChannelIdx,
(long) idxShareSeriesIdx,
true ); // recurse only once
}
}
else if( pvectSeriesArray )
{
// Generate the new series array
countPoints = _GenerateSeriesCount( idStorageMethod, pvectSeriesArray);
}
}
return countPoints;
}
BOOL CPQDIF_R_Observation::GetSeriesBaseType
(
long idxChannel,
long idxSeries,
long& nSeriesBaseType
)
{
BOOL status = FALSE;
int idx;
CPQDIF_Element * pel;
CPQDIF_E_Collection * pcol;
CPQDIF_E_Scalar * psc;
CPQDIF_E_Vector * pvectSeriesArray;
long typePhysical;
PQDIFValue value;
double valueReal;
double rBaseValue = 1.0;
double rScale = 1.0;
double rOffset = 0.0;
bool gotShareChannel = false;
bool gotShareSeries = false;
bool isShared = false;
UINT4 idxShareChannelIdx = 0;
UINT4 idxShareSeriesIdx = 0;
pcol = GetOneSeries( idxChannel, idxSeries );
if( pcol )
{
status = TRUE;
// Loop through all elements in the series collection
for( idx = 0; idx < pcol->GetCount(); idx++ )
{
pel = pcol->GetElement( idx );
if( pel )
{
if( pel->GetElementType() == ID_ELEMENT_TYPE_SCALAR )
{
psc = (CPQDIF_E_Scalar *) pel;
// If it's REAL4 or REAL8, go ahead and pull it out
valueReal = 0.0;
psc->GetValue( typePhysical, value );
nSeriesBaseType = typePhysical;
}
if( pel->GetElementType() == ID_ELEMENT_TYPE_VECTOR
&& PQDIF_IsEqualGUID( pel->GetTag(), tagSeriesValues ) )
{
pvectSeriesArray = (CPQDIF_E_Vector *) pel;
nSeriesBaseType = pvectSeriesArray->GetPhysicalType();
}
} // if( pel )
}
}
return status;
}
double * CPQDIF_R_Observation::NewResolvedSeries
(
long idxChannel,
long idxSeries,
long& countPoints,
bool noShare
)
{
bool status = false;
int idx;
double * arValues = NULL;
CPQDIF_Element * pel = NULL;
CPQDIF_E_Collection * pcol = NULL;
CPQDIF_E_Scalar * psc = NULL;
CPQDIF_E_Vector * pvectSeriesArray = NULL;
long typePhysical;
PQDIFValue value;
double valueReal;
double rBaseValue = 1.0;
double rScale = 1.0;
double rOffset = 0.0;
long idxChannelDefn = 0;
string name;
UINT4 idPhase;
GUID idQuantityType;
UINT4 idQuantityMeasured;
UINT4 idQuantityUnits;
GUID idQuantityCharacteristic;
GUID idValueType;
UINT4 idStorageMethod;
bool gotShareChannel = false;
bool gotShareSeries = false;
bool isShared = false;
UINT4 idxShareChannelIdx = 0;
UINT4 idxShareSeriesIdx = 0;
// Verify that we're in an observation record
// Requires a data source record
if( m_record && m_pds && idxChannel >= 0 && idxSeries >= 0)
{
// Find the channel defn index
status = GetChannelDefnIdx( idxChannel, idxChannelDefn );
// Fail if we got a bogus index
if( status && idxChannelDefn < 0 )
status = false;
}
// Gather information from the channel & series definitions
if( status )
{
status = m_pds->GetChannelDefnInfo( idxChannelDefn, name, idPhase, idQuantityType, idQuantityMeasured );
}
if( status )
{
status = m_pds->GetSeriesDefnInfo( idxChannelDefn, idxSeries,
idQuantityUnits, idValueType, idQuantityCharacteristic, idStorageMethod );
}
if( status )
{
status = false;
// Find the series
pcol = GetOneSeries( idxChannel, idxSeries );
if( pcol )
{
status = true;
// Loop through all elements in the series collection
for( idx = 0; idx < pcol->GetCount(); idx++ )
{
pel = pcol->GetElement( idx );
if( pel )
{
if( pel->GetElementType() == ID_ELEMENT_TYPE_SCALAR )
{
psc = (CPQDIF_E_Scalar *) pel;
// If it's REAL4 or REAL8, go ahead and pull it out
valueReal = 0.0;
psc->GetValue( typePhysical, value );
if (typePhysical == ID_PHYS_TYPE_INTEGER4)
{
valueReal = value.int4;
}
if( typePhysical == ID_PHYS_TYPE_REAL4 )
{
valueReal = value.real4;
}
if( typePhysical == ID_PHYS_TYPE_REAL8 )
{
valueReal = value.real8;
}
if( PQDIF_IsEqualGUID( pel->GetTag(), tagSeriesBaseQuantity ) )
{
rBaseValue = valueReal;
}
if( PQDIF_IsEqualGUID( pel->GetTag(), tagSeriesScale ) )
{
rScale = valueReal;
}
if( PQDIF_IsEqualGUID( pel->GetTag(), tagSeriesOffset ) )
{
rOffset = valueReal;
}
if( PQDIF_IsEqualGUID( pel->GetTag(), tagSeriesShareChannelIdx ) )
{
gotShareChannel = TRUE;
psc->GetValueUINT4( idxShareChannelIdx );
}
if( PQDIF_IsEqualGUID( pel->GetTag(), tagSeriesShareSeriesIdx ) )
{
gotShareSeries = TRUE;
psc->GetValueUINT4( idxShareSeriesIdx );
}
}
if( pel->GetElementType() == ID_ELEMENT_TYPE_VECTOR
&& PQDIF_IsEqualGUID( pel->GetTag(), tagSeriesValues ) )
{
pvectSeriesArray = (CPQDIF_E_Vector *) pel;
}
} // if( pel )
}
}
}
// Generate the series data
if( status )
{
if( gotShareChannel && gotShareSeries )
{
// We're sharing the series from somwhere else --
// generate it from the shared indices
if( !noShare )
{
arValues = NewResolvedSeries(
(long) idxShareChannelIdx,
(long) idxShareSeriesIdx,
countPoints, true );
}
else
{
// Can't generate! The file is trying to share a series
// from another shared series. This is not legal.
arValues = NULL;
}
}
else if( pvectSeriesArray )
{
// Generate the new series array
arValues = _GenerateSeriesData( idxChannelDefn, idStorageMethod,
rBaseValue, rScale, rOffset, pvectSeriesArray, countPoints );
}
else
{
// Can't generate!
arValues = NULL;
}
}
return arValues;
}
TIMESTAMPPQDIF * CPQDIF_R_Observation::NewResolvedSeriesTimeStamp
(
long idxChannel,
long idxSeries,
long& countPoints,
bool noShare
)
{
TIMESTAMPPQDIF * result = NULL;
CPQDIF_E_Collection * pcol;
CPQDIF_Element * pel;
CPQDIF_E_Scalar * psc;
CPQDIF_E_Vector * pvectSeriesArray;
// Shared?
BOOL gotShareChannel = FALSE;
BOOL gotShareSeries = FALSE;
UINT4 idxShareChannelIdx = 0;
UINT4 idxShareSeriesIdx = 0;
pcol = GetOneSeries( idxChannel, idxSeries );
if( pcol )
{
// Is this sucker shared?
pel = pcol->GetElement( tagSeriesShareChannelIdx );
if( pel && pel->GetElementType() == ID_ELEMENT_TYPE_SCALAR )
{
gotShareChannel = TRUE;
psc = static_cast<CPQDIF_E_Scalar *>( pel );
psc->GetValueUINT4( idxShareChannelIdx );
}
pel = pcol->GetElement( tagSeriesShareSeriesIdx );
if( pel && pel->GetElementType() == ID_ELEMENT_TYPE_SCALAR )
{
gotShareSeries = TRUE;
psc = static_cast<CPQDIF_E_Scalar *>( pel );
psc->GetValueUINT4( idxShareSeriesIdx );
}
if( gotShareSeries && gotShareSeries && !noShare )
{
// SHARED.
// Allow ONE level of recursion -- no more.
result = NewResolvedSeriesTimeStamp( idxShareChannelIdx,
idxShareSeriesIdx, countPoints, true );
}
else
{
// NOT SHARED.
// Try to decode it the normal way.
pel = pcol->GetElement( tagSeriesValues );
if( pel->GetElementType() == ID_ELEMENT_TYPE_VECTOR )
{
pvectSeriesArray = static_cast<CPQDIF_E_Vector *>( pel );
// Determine size/allocate space for the timestamp array
if( pvectSeriesArray->GetCount( countPoints ) )
{
result = new TIMESTAMPPQDIF[ countPoints ];
if( result )
{
// Is it already in timestamp form?
if( pvectSeriesArray->GetPhysicalType() == ID_PHYS_TYPE_TIMESTAMPPQDIF )
{
// We're done!
countPoints = pvectSeriesArray->GetValuesTimeStamp ( result, countPoints );
}
else
{
// Fabricate it from starting time stamp and second offsets
double * seconds = NewResolvedSeries( idxChannel, idxSeries, countPoints, true );
if( seconds )
{
_GenerateTimeStampArray( result, seconds, countPoints );
delete [] seconds;
}
}
}
}
}
}
}
return result;
}
bool CPQDIF_R_Observation::GetChannelDefnIdx
(
long idxChannel,
long& idxChannelDefn
)
{
bool status = false;
CPQDIF_E_Collection * pcollOneChannel;
CPQDIF_E_Scalar * psc;
UINT4 idx;
// Init
status = false;
idxChannelDefn = 0;
// Find the channel
pcollOneChannel = GetOneChannel( idxChannel );
if( pcollOneChannel )
{
// This is where the index should be
psc = m_record->FindScalarInCollection( pcollOneChannel, tagChannelDefnIdx );
if( psc )
{
status = psc->GetValueUINT4( idx );
idxChannelDefn = (long) idx;
status = TRUE;
}
}
return status;
}
CPQDIF_E_Collection * CPQDIF_R_Observation::GetChannelInstances( void )
{
CPQDIF_E_Collection * pcollChannels;
// Create the collection if it does not yet exist.
pcollChannels = m_record->FindCollectionInCollection( m_record->m_pcollMain, tagChannelInstances );
if( !pcollChannels )
{
pcollChannels = (CPQDIF_E_Collection *) theFactory.NewElement( ID_ELEMENT_TYPE_COLLECTION );
if( pcollChannels )
{
pcollChannels->SetTag( tagChannelInstances );
m_record->m_pcollMain->Add( pcollChannels );
}
}
return pcollChannels;
}
CPQDIF_E_Collection * CPQDIF_R_Observation::GetOneChannel( long idxChannel )
{
CPQDIF_E_Collection * pcolReturn = NULL;
CPQDIF_E_Collection * pcolInstances = GetChannelInstances();
CPQDIF_Element * pel;
if( pcolInstances )
{
pel = pcolInstances->GetElement( idxChannel );
if( pel )
{
if( pel->GetElementType() == ID_ELEMENT_TYPE_COLLECTION
&& PQDIF_IsEqualGUID( pel->GetTag(), tagOneChannelInst ) )
{
pcolReturn = (CPQDIF_E_Collection *) pel;
}
}
}
return pcolReturn;
}
CPQDIF_E_Collection * CPQDIF_R_Observation::GetSeriesInstances
(
CPQDIF_E_Collection * pcolChannel
)
{
return m_record->FindCollectionInCollection( pcolChannel, tagSeriesInstances );
}
CPQDIF_E_Collection * CPQDIF_R_Observation::GetOneSeries
(
CPQDIF_E_Collection * pcolChannel,
long idxSeries
)
{
CPQDIF_E_Collection * pcolReturn = NULL;
CPQDIF_E_Collection * pcolSeriesInstances = NULL;
CPQDIF_Element * pel;
if( pcolChannel )
{
// Get the series instances for this channel instance
pcolSeriesInstances = GetSeriesInstances( pcolChannel );
if( pcolSeriesInstances )
{
// Find the specific series instance
pel = pcolSeriesInstances->GetElement( idxSeries );
if( pel )
{
if( pel->GetElementType() == ID_ELEMENT_TYPE_COLLECTION
&& PQDIF_IsEqualGUID( pel->GetTag(), tagOneSeriesInstance ) )
{
// Return it!
pcolReturn = (CPQDIF_E_Collection *) pel;
}
}
}
}
return pcolReturn;
}
CPQDIF_E_Collection * CPQDIF_R_Observation::GetOneSeries
(
long idxChannel,
long idxSeries
)
{
CPQDIF_E_Collection * pcolReturn = NULL;
CPQDIF_E_Collection * pcolOneChannel = NULL;
pcolOneChannel = GetOneChannel( idxChannel );
pcolReturn = GetOneSeries( pcolOneChannel, idxSeries );
return pcolReturn;
}
long CPQDIF_R_Observation::_GenerateSeriesCount
(
UINT4 idStorageMethod,
CPQDIF_E_Vector * pvectSeriesArray
)
{
long countPoints = 0;
if( idStorageMethod & ID_SERIES_METHOD_VALUES )
{
// Straight vector.
pvectSeriesArray->GetCount( countPoints );
}
else if( idStorageMethod & ID_SERIES_METHOD_INCREMENT )
{
// Incremental storage method ... some assembly required.
long countValues;
long idxValue;
double rCount;
// Read in the rate change list
pvectSeriesArray->GetCount( countValues );
if( countValues > 0 )
{
// Grab only the point counts at indices 1, 3, 5, ...
for( idxValue = 1; idxValue < countValues; idxValue += 2 )
{
pvectSeriesArray->GetValue( idxValue, rCount );
countPoints += (long) rCount;
}
}
}
else
{
// No third option!
}
return countPoints;
}
double * CPQDIF_R_Observation::_GenerateSeriesData
(
int idxChannelDefn,
UINT4 idStorageMethod,
double rBaseValue,
double rScale,
double rOffset,
CPQDIF_E_Vector * pvectSeriesArray,
long& countPoints
)
{
double * arValues = NULL;
double * prTempValues;
long idxPoint;
long countValues;
long idxValue;
bool useScale = false;
bool useCal = false;
// Unused parameter
rBaseValue = rBaseValue;
// Get raw number of values in the vector. This may be the actual
// number of points.
pvectSeriesArray->GetCount( countValues );
// Determine how many total points
countPoints = _GenerateSeriesCount( idStorageMethod, pvectSeriesArray );
if( idStorageMethod & ID_SERIES_METHOD_VALUES )
{
// Straight vector. No assembly necessary.
// The two counts must be identical.
if( countPoints > 0 && countPoints == countValues )
{
// We already have the number of points...
arValues = new double[ countPoints ];
prTempValues = arValues;
for( idxPoint = 0; idxPoint < countPoints; idxPoint++, prTempValues++ )
{
pvectSeriesArray->GetValue( idxPoint, *prTempValues );
}
}
}
else if( idStorageMethod & ID_SERIES_METHOD_INCREMENT )
{
// Incremental storage method ... some assembly required.
double valueNext;
double rCount;
double rRate ;
long countChanges;
long idxChange;
long countPointsThisChange;
// Go through the rate change list and generate the array.
if( countPoints > 0 )
{
arValues = new double[ countPoints ];
if( arValues )
{
// Init -- get ready for loops
prTempValues = arValues;
valueNext = 0.0; // First item will be zero
// Determine total number of rate changes [0]
pvectSeriesArray->GetValue( 0, rCount );
countChanges = (long) rCount;
// Get counts and rate changes ...
for( idxChange = 0; idxChange < countChanges; idxChange++ )
{
// Calculate index into value array ...
idxValue = ( idxChange * 2 ) + 1;
// Get data ...
pvectSeriesArray->GetValue( idxValue + 0, rCount ); // Count @ rate
pvectSeriesArray->GetValue( idxValue + 1, rRate ); // Rate
countPointsThisChange = (long) rCount;
// Generate points from the data ...
for( idxPoint = 0; idxPoint < countPointsThisChange; idxPoint++, prTempValues++ )
{
// Store current point.
*prTempValues = valueNext;
// Calculate next point.
valueNext += rRate;
} // for( points );
} // for( changes )
}
}
}
else
{
// No third option!
arValues = NULL;
}
// Scale & offset?
if( idStorageMethod & ID_SERIES_METHOD_SCALED )
{
// Scale/offset should already be set.
useScale = true;
}
else
{
// Default values for scale/offset
rScale = 1.0;
rOffset = 0.0;
useScale = false;
}
// CT/PT ratios?
useCal = _GetCalibrationRatio( idxChannelDefn, rScale );
if( useCal )
{
// The scale has now been adjusted to apply
// the calibration ratio.
useScale = true;
}
// Adjust, if necessary.
if( useScale )
{
if( arValues && countPoints > 0 )
{
prTempValues = arValues;
for( idxPoint = 0; idxPoint < countPoints; idxPoint++, prTempValues++ )
{
// Apply scale first, then offset
*prTempValues *= rScale;
*prTempValues += rOffset;
} // for( points );
}
}
return arValues;
}
bool CPQDIF_R_Observation::_GenerateTimeStampArray
(
TIMESTAMPPQDIF * result,
double * seconds,
long countPoints
)
{
bool status = false;
TIMESTAMPPQDIF tsStart;
TIMESTAMPPQDIF tsTemp;
string name;
TIMESTAMPPQDIF * resTemp = result;
double * secTemp = seconds;
// Get start time for the entire observation. If successful then ...
status = GetInfo( tsStart, tsTemp, name );
if (tsStart.day > 0) status = 1;
if( status )
{
// For each value do ...
for( int idx = 0; idx < countPoints; idx++, resTemp++, secTemp++ )
{
// Get starting time
*resTemp = tsStart;
// Add seconds to it
_AddSeconds( *resTemp, *secTemp );
} // for( stamps )
}
return status;
}
bool CPQDIF_R_Observation::_GetCalibrationRatio
(
int idxChannelDefn,
double& rScale
)
{
bool status = false;
if( m_psett )
{
TIMESTAMPPQDIF tsTemp;
bool useCal = false;
bool useTrans = false; // Not used
bool gotInfo = m_psett->GetInfo( tsTemp, tsTemp, tsTemp, useCal, useTrans );
if( gotInfo && useCal )
{
long countChannels;
countChannels = m_psett->GetCountChannels();
for( long idxChannel = 0; idxChannel < countChannels; idxChannel++ )
{
UINT4 idxChannelDefnCurrent;
gotInfo = m_psett->GetChannelInfo( idxChannel, idxChannelDefnCurrent);
if( gotInfo )
{
// Is this the information for the correct channel defn?
if( idxChannelDefn == (int) idxChannelDefnCurrent )
{
UINT4 xdTransformerTypeID;
REAL8 xdSystemSideRatio;
REAL8 xdMonitorSideRatio;
CPQDIF_E_Vector xdFrequencyResponse;
gotInfo = m_psett->GetChanTrans( idxChannel,
xdTransformerTypeID,
xdSystemSideRatio, xdMonitorSideRatio,
xdFrequencyResponse );
if( gotInfo )
{
// Looks like we got it...
rScale *= xdMonitorSideRatio;
rScale /= xdSystemSideRatio;
status = true;
break;
}
}
}
}
}
}
return status;
}