view Allan.c @ 67:0159abc1a9d8

Fix slope measurement For the update algorithm to work correclty the slope measurement must be updated before the mean measurement. Other code is affected by the same issue.
author Daniele Nicolodi <daniele.nicolodi@obspm.fr>
date Mon, 29 Oct 2012 14:48:08 +0100
parents d9aae7d7f2c6
children 0e9f95525a8f
line wrap: on
line source

#include <ansi_c.h>
#include <userint.h>

#include "YLCStuff.h"

#include "FXAllan.h"   // Auto generated panel definitions and protypes
#include "Allan.h"	   // My own .h file, containing prototypes and definitions for the class Allan...



// ******************* Member functions : constructor and destructor *************************

int Allan_InitPanel(Allan_Data * Instance, char * title, double Normalizer, void (*OnCloseFunc)(int)) {
	
	int i ;
	
	if ((Instance->AllanPanel = LoadPanel (0, "FXAllan.uir", ALLANPANEL)) < 0)
	return -1;
	SetPanelAttribute(Instance->AllanPanel, ATTR_TITLE, title) ; 
	SetPanelAttribute (Instance->AllanPanel, ATTR_CALLBACK_DATA, (void *)Instance); // the panel callback therefore knows which data structure it is associated to
	Instance->OnClosePanel = OnCloseFunc ;
	for (i=0 ; i<ALLAN_MAXPOINTSNUMBER ; i++) {
		Instance->AllanVar[i] = 0 ;
		Instance->LastMean[i] = 0 ; 
		Instance->BlocksNumber[i] = 0 ;
		Instance->CurrentAverage[i] = 0 ; 
		Instance->NbCurrentAverage[i] = 0 ;
	} ;
	Instance->Drift = 0 ;
	DisplayPanel (Instance->AllanPanel);
	SetCtrlVal(Instance->AllanPanel, ALLANPANEL_NORMALIZER, Normalizer) ;
	return 0 ;
	}



int Allan_ClosePanel(Allan_Data * Instance) {
	Instance->OnClosePanel(Instance->AllanPanel) ;
	DiscardPanel (Instance->AllanPanel); 
	return 0;
	}

	

// ******************** Member functions, callbacks (private) *******************************    


int  CVICALLBACK Allan_CB_Reset(int panel, int control, int event,
		void *callbackData, int eventData1, int eventData2)
{
	int i ;
	Allan_Data * Instance = NULL;
	
	switch(event) {

		case EVENT_COMMIT:
			GetPanelAttribute (panel, ATTR_CALLBACK_DATA, &Instance);
			Allan_Reset(Instance) ;	
			break;
			
		case EVENT_RIGHT_CLICK:

			break;
		}
		
	return 0;
}

int CVICALLBACK Allan_CB_ChangeMax (int panel, int control, int event,
		void *callbackData, int eventData1, int eventData2)
{  
	int YMin, YMax ;

	switch (event)
		{
		case EVENT_COMMIT:
			GetCtrlVal(panel, ALLANPANEL_MIN, &YMin) ;
			GetCtrlVal(panel, ALLANPANEL_MAX, &YMax) ;
			if (YMin<YMax) {
				SetAxisScalingMode(panel, ALLANPANEL_ALLANPLOT, VAL_LEFT_YAXIS, VAL_MANUAL, pow(10,(double)YMin), pow(10,(double)YMax) ) ;
				SetCtrlVal(panel, ALLANPANEL_CHECKBOX_AUTOSCALE, FALSE) ; 
				} ;
			break;
			
		case EVENT_RIGHT_CLICK:

			break;
		}	
	return 0;
}

int CVICALLBACK Allan_CB_ChangeMin (int panel, int control, int event,
		void *callbackData, int eventData1, int eventData2)
{   
	int YMin, YMax ;
	
	switch (event)
		{
		case EVENT_COMMIT:
				GetCtrlVal(panel, ALLANPANEL_MIN, &YMin) ;
				GetCtrlVal(panel, ALLANPANEL_MAX, &YMax) ;
				if (YMin<YMax ) {     
					SetAxisScalingMode(panel, ALLANPANEL_ALLANPLOT, VAL_LEFT_YAXIS, VAL_MANUAL, pow(10,(double)YMin), pow(10,(double)YMax) ) ;
					SetCtrlVal(panel, ALLANPANEL_CHECKBOX_AUTOSCALE, FALSE) ;
					} ;
			break;
			
		case EVENT_RIGHT_CLICK:

			break;
		}	  
	return 0;
}


int CVICALLBACK Allan_CB_ChangeAutoScale (int panel, int control, int event,
		void *callbackData, int eventData1, int eventData2)
{  
	return 0; 
} 


int CVICALLBACK Allan_CB_ChangeNormalizer (int panel, int control, int event,
		void *callbackData, int eventData1, int eventData2)
{  /*
	bool AutoScale = FALSE;
	int NotCare  = 20000000 ;
	double YMin = 10000000 , YMax = 64000000 ;
	
	switch (event)
		{
		case EVENT_COMMIT:
			GetCtrlVal(panel, ALLANPANEL_CHECKBOX_AUTOSCALE, &AutoScale) ;
			if (AutoScale) {
				SetAxisScalingMode(panel, ALLANPANEL_ALLANPLOT, VAL_LEFT_YAXIS, VAL_AUTOSCALE, YMin, YMax) ;
				GetAxisScalingMode(panel, ALLANPANEL_ALLANPLOT,VAL_LEFT_YAXIS, &NotCare, &YMin, &YMax ) ;
				SetCtrlVal(panel, ALLANPANEL_MIN, YMin);
				SetCtrlVal(panel, ALLANPANEL_MAX, YMax);
				}
			else {
				GetCtrlVal(panel, ALLANPANEL_MIN, &YMin);
				GetCtrlVal(panel, ALLANPANEL_MAX, &YMax);
				SetAxisScalingMode(panel, ALLANPANEL_ALLANPLOT, VAL_LEFT_YAXIS, VAL_MANUAL, YMin, YMax) ;
				} ;
			break;
		case EVENT_RIGHT_CLICK:

			break;
		}	 */
	return 0; 
} 



// ******************** Member functions, public *****************************************    

int Allan_Reset(Allan_Data * Instance) {
	
	int i ;
	
	for (i=0 ; i<ALLAN_MAXPOINTSNUMBER ; i++) {
		Instance->AllanVar[i] = 0 ;
		Instance->LastMean[i] = 0 ; 
		Instance->BlocksNumber[i] = 0 ;
		Instance->CurrentAverage[i] = 0 ; 
		Instance->NbCurrentAverage[i] = 0 ;
	} ;
	
	return 0 ;

}


int Allan_AddFrequency(Allan_Data * Instance, double Freq) {

	int i, N;  
	double CurrentMean, LastMean, Drift, Mean, Normalizer ;
	
	N = Instance->BlocksNumber[0]+1 ;	   // the total number of points used, usefull to calculate drift rate
	Mean = Instance->Mean ;
	Drift = Instance->Drift ;
	
	GetCtrlVal(Instance->AllanPanel, ALLANPANEL_NORMALIZER, &Normalizer);
	
	if (N > 1) {   // Drift measure needs at least 2 values !
		Instance->Drift = (Drift*(N-2) + 6*(Freq-Mean)/N)/(N+1) ;
		SetCtrlVal(Instance->AllanPanel, ALLANPANEL_DRIFT, Instance->Drift/Normalizer ) ;
	}
	
	// update mean value (usefull to calculate drift rate with linear regression incremental algorithm...)
	Instance->Mean = (Mean*(N-1)+Freq)/N ; 
	
	
	for (i=0 ; i<ALLAN_MAXPOINTSNUMBER ; i++) {
		Instance->CurrentAverage[i] = (Instance->CurrentAverage[i]*Instance->NbCurrentAverage[i] + Freq)
											/(Instance->NbCurrentAverage[i]+1) ;
		Instance->NbCurrentAverage[i] +=1 ;
		
		if (Instance->NbCurrentAverage[i] >= pow(2,i) ) {

			CurrentMean = Instance->CurrentAverage[i];
			LastMean = Instance->LastMean[i] ;
			N = Instance->BlocksNumber[i] ;
			N++ ;
			Instance->CurrentAverage[i] = 0 ;
			Instance->NbCurrentAverage[i] = 0 ;
			if (N>1) {
				Instance->AllanVar[i] = (Instance->AllanVar[i]*(N-2)
										+0.5*pow(CurrentMean-LastMean,2))/(N-1)  ;
			}
			else { // ie if N=1, which is realized for the first completed block
				Instance->FirstMean[i] = CurrentMean ;
			} ;
			Instance->LastMean[i] = CurrentMean ;
			Instance->BlocksNumber[i] = N ;
		} ;
	} ;
	
	Allan_Display(Instance, VAL_WHITE, VAL_BLUE) ;
	
	return 0 ;
}

int Allan_Display (Allan_Data * Instance, int ColorPt, int ColorErrorBar){

	int PointsNumber = ALLAN_MAXPOINTSNUMBER ;
	int i, N ;
	double X[ALLAN_MAXPOINTSNUMBER] ;
	double Y[ALLAN_MAXPOINTSNUMBER] ;
	double Normalizer, DriftTau, FirstFreq, LastFreq, Error ;
	bool DeDrift ;
	
	GetCtrlVal(Instance->AllanPanel, ALLANPANEL_NORMALIZER, &Normalizer) ;
	GetCtrlVal(Instance->AllanPanel, ALLANPANEL_DEDRIFT, &DeDrift) ;
	
	for (i=0 ; i<PointsNumber ; i++) {
		X[i] = pow(2,i) ;
		if (!DeDrift) { Y[i] = sqrt(Instance->AllanVar[i])/Normalizer ;}
		else { 
			DriftTau = Instance->Drift*X[i] ;
			N = Instance->BlocksNumber[i] ;
			if (N>=2) { // if enough data to calculate AVAR for tau = 2^i*tau0, and therefore, AllanVar[i] is meaningful
				FirstFreq = Instance->FirstMean[i] ;
				LastFreq = Instance->LastMean[i] ;
				Y[i] = sqrt(Instance->AllanVar[i]+DriftTau*(DriftTau/2-(LastFreq-FirstFreq)/(N-1)))/Normalizer ;
				// Not totaly sure it works... to be checked thoroughly   
				}
			else { Y[i] = 0 ; } ;
			} ;
	} ;
	
	DeleteGraphPlot(Instance->AllanPanel, ALLANPANEL_ALLANPLOT, -1, VAL_IMMEDIATE_DRAW) ; 
	PlotXY (Instance->AllanPanel, ALLANPANEL_ALLANPLOT, X, Y, PointsNumber,
			VAL_DOUBLE, VAL_DOUBLE, VAL_SCATTER, VAL_SOLID_SQUARE, VAL_SOLID, 1, ColorPt);
	
	for (i=0 ; i<PointsNumber ; i++) {
		Error = 1/sqrt(Instance->BlocksNumber[i]) ;
		PlotLine  (Instance->AllanPanel, ALLANPANEL_ALLANPLOT, X[i], Y[i]*(1-Error), X[i], Y[i]*(1+Error), ColorErrorBar);
	} ;
 
	
	return 0 ;
}

int Allan_DisplayErrorBars (Allan_Data * Instance, int color){

	int i;
	double X[ALLAN_MAXPOINTSNUMBER] ;
	double Val, Error, Normalizer;
	
	GetCtrlVal(Instance->AllanPanel, ALLANPANEL_NORMALIZER, &Normalizer) ;
	for (i=0 ; i<ALLAN_MAXPOINTSNUMBER ; i++) {
		X[i] = pow(2,i) ;
		Val = sqrt(Instance->AllanVar[i])/Normalizer ;
		Error = 1/sqrt(Instance->BlocksNumber[i]) ;      
		PlotLine  (Instance->AllanPanel, ALLANPANEL_ALLANPLOT, X[i], Val*(1-Error), X[i], Val*(1+Error), color);
	} ;
	
	return 0 ;
}

int CVICALLBACK CB_GeneralAllanPanel (int panel, int event, void *callbackData,
		int eventData1, int eventData2)
{
	Allan_Data * Instance = NULL;
	
	
	switch (event)
		{
		case EVENT_GOT_FOCUS:

			break;
		case EVENT_LOST_FOCUS:

			break;
		case EVENT_CLOSE:
			GetPanelAttribute (panel, ATTR_CALLBACK_DATA, &Instance);
			Allan_ClosePanel(Instance) ;
			
			break;
		}
	return 0;
}