view Allan.c @ 61:37075b60408b

Fix N2 measurement after cleanup. Further simplification
author Daniele Nicolodi <daniele.nicolodi@obspm.fr>
date Thu, 18 Oct 2012 12:24:31 +0200
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;
}