view Allan.c @ 135:77539f2597b1

Code cleanup
author Daniele Nicolodi <daniele.nicolodi@obspm.fr>
date Wed, 22 Jan 2014 12:29:38 +0100
parents bd28161e5ac2
children 7b9cf3d4346e
line wrap: on
line source

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

#include "YLCStuff.h"
#include "FXAllan.h"
#include "Allan.h"

#define DATAPOINT_COLOR VAL_RED
#define ERRORBAR_COLOR VAL_RED


static void Allan_Reset(Allan_Data * Instance);
static void Allan_Display(Allan_Data * Instance);


void Allan_InitPanel(Allan_Data * Instance, const char *title, double normalization, int parent, int control) 
{
	if ((Instance->AllanPanel = LoadPanel (0, "FXAllan.uir", ALLANPANEL)) < 0)
		return;
	
	Allan_Reset(Instance);
	Instance->normalization = normalization;
	Instance->autoscale = FALSE;
	Instance->active = TRUE;
	Instance->parent = parent;
	Instance->control = control;
	
	SetPanelAttribute(Instance->AllanPanel, ATTR_TITLE, title); 
	SetPanelAttribute (Instance->AllanPanel, ATTR_CALLBACK_DATA, (void *)Instance);
	DisplayPanel (Instance->AllanPanel);
	SetCtrlVal(Instance->AllanPanel, ALLANPANEL_NORMALIZER, normalization);
}


void Allan_ClosePanel(Allan_Data * Instance)
{
	Instance->active = FALSE;
	SetCtrlVal(Instance->parent, Instance->control, FALSE);
	DiscardPanel (Instance->AllanPanel);
}


void Allan_AddFrequency(Allan_Data * Instance, double Freq)
{
	/* total number of points used. used to calculate the drift rate */
	int N = 1 + Instance->BlocksNumber[0];
	double Mean = Instance->Mean;
	double Drift = Instance->Drift;
	double Normalizer = Instance->normalization;
	
	/* compute drift rate */
	if (N > 1) {
		Instance->Drift = (Drift * (N - 2) + 6 * (Freq - Mean) / N) / (N + 1);
		SetCtrlVal(Instance->AllanPanel, ALLANPANEL_DRIFT, Instance->Drift/Normalizer);
	}
	Instance->Mean = (Mean * (N - 1) + Freq) / N; 
	
	/* compute allan deviation */
	for (int 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) ) {
			double CurrentMean = Instance->CurrentAverage[i];
			double 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);
}


/* private */

static void Allan_Reset(Allan_Data *Instance)
{
	memset(Instance->AllanVar, 0, sizeof(Instance->AllanVar));
	memset(Instance->FirstMean, 0, sizeof(Instance->FirstMean));
	memset(Instance->LastMean, 0, sizeof(Instance->LastMean));
	memset(Instance->BlocksNumber, 0, sizeof(Instance->BlocksNumber));
	memset(Instance->CurrentAverage, 0, sizeof(Instance->CurrentAverage));
	memset(Instance->NbCurrentAverage, 0, sizeof(Instance->NbCurrentAverage));
	Instance->Drift = 0;
	Instance->Mean = 0;
}

	
static void Allan_Display(Allan_Data *Instance)
{
	int i, N;
	double X[ALLAN_MAXPOINTSNUMBER];
	double Y[ALLAN_MAXPOINTSNUMBER];
	double Normalizer = Instance->normalization;
	double DriftTau, FirstFreq, LastFreq, Error;
	int dedrift;
	
	GetCtrlVal(Instance->AllanPanel, ALLANPANEL_DEDRIFT, &dedrift);
	
	for (i = 0; i < ALLAN_MAXPOINTSNUMBER; i++) {
		X[i] = pow(2, i);
		if (dedrift) {
			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;
			}
		} else {
			Y[i] = sqrt(Instance->AllanVar[i])/Normalizer;
		}
	}
	
	DeleteGraphPlot(Instance->AllanPanel, ALLANPANEL_ALLANPLOT, -1, VAL_IMMEDIATE_DRAW); 
	PlotXY(Instance->AllanPanel, ALLANPANEL_ALLANPLOT, X, Y, ALLAN_MAXPOINTSNUMBER,
			VAL_DOUBLE, VAL_DOUBLE, VAL_SCATTER, VAL_SOLID_SQUARE, VAL_SOLID, 1, DATAPOINT_COLOR);
	
	for (i = 0; i < ALLAN_MAXPOINTSNUMBER; i++) {
		Error = 1/sqrt(Instance->BlocksNumber[i]);
		PlotLine(Instance->AllanPanel, ALLANPANEL_ALLANPLOT, X[i], Y[i]*(1-Error), X[i], Y[i]*(1+Error), ERRORBAR_COLOR);
	}
}


/* callbacks */

int  CVICALLBACK Allan_CB_Reset(int panel, int control, int event,
		void *callbackData, int eventData1, int eventData2)
{
	switch(event)
	{
		case EVENT_COMMIT:
			Allan_Data *data;
			GetPanelAttribute(panel, ATTR_CALLBACK_DATA, &data);
			Allan_Reset(data);
			break;
	}
	return 0;
}


int CVICALLBACK Allan_CB_ChangeYLim (int panel, int control, int event,
		void *callbackData, int eventData1, int eventData2)
{
	switch (event)
	{
		case EVENT_COMMIT:
			int YMin, YMax;
			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;
	}	
	return 0;
}


int CVICALLBACK Allan_CB_ChangeAutoScale (int panel, int control, int event,
		void *callbackData, int eventData1, int eventData2)
{  
	switch (event)
	{
		case EVENT_COMMIT:
			Allan_Data *data;
			GetPanelAttribute(panel, ATTR_CALLBACK_DATA, &data);
			GetCtrlVal(panel, control, &(data->normalization));
			Allan_Display(data);
			break;
	}
	return 0; 
} 


int CVICALLBACK Allan_CB_ChangeNormalization (int panel, int control, int event,
		void *callbackData, int eventData1, int eventData2)
{
	switch (event)
	{
		case EVENT_COMMIT:
			Allan_Data *data;
			GetPanelAttribute(panel, ATTR_CALLBACK_DATA, &data);
			GetCtrlVal(panel, control, &(data->normalization));
			Allan_Display(data);
			break;
	}
	return 0; 
} 


int CVICALLBACK CB_GeneralAllanPanel (int panel, int event, void *callbackData,
		int eventData1, int eventData2)
{
	switch (event)
	{
		case EVENT_CLOSE:
			Allan_Data *data;
			GetPanelAttribute(panel, ATTR_CALLBACK_DATA, &data);
			Allan_ClosePanel(data);
			break;
	}
	return 0;
}