Mercurial > hg > fxanalyse
view Allan.c @ 132:fbd72d87b4dc
Support graceful intrerruption of N3 measurement. Minor user interface fixes
author | Daniele Nicolodi <daniele.nicolodi@obspm.fr> |
---|---|
date | Tue, 17 Dec 2013 17:21:17 +0100 |
parents | 0e9f95525a8f |
children | bd28161e5ac2 |
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) { 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; }