📄 convertregularxyz.c
字号:
/*------------------------------------------------------------------------------*
* File Name: ConvertRegularXYZ.c *
* Creation: ER, 24th September 2001 *
* Purpose: OriginC function to examine XYZ data for Regular Matrix Conversion *
* Copyright (c) OriginLab Corp.2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 *
* All Rights Reserved *
* *
* Modification Log: *
*------------------------------------------------------------------------------*/
////////////////////////////////////////////////////////////////////////////////////
#include <origin.h>
//#include <data.h>
//#include <math.h>
////////////////////////////////////////////////////////////////////////////////////
//
// prototype of functions in this file:
//
int ConvertRegularXYZ(string winData, int iXCol, int iYCol, int iZCol, string winTemp);
int FindStep(Dataset<double> &v);
//
////////////////////////////////////////////////////////////////////////////////////
//
// ConvertRegularXYZ:
//
// The function ConvertRegularXYZ examines the raw X,Y,Z data checking for irregularities in step size,
// large deviations within a step etc. If the function returns a value of 0, then the raw data passed these
// tests, and the data corrected and copied onto the temporary worksheet can then be used to perform a
// regular X,Y,Z matrix conversion using Origin's built-in conversion ccode.
// A few details of the function follow:
// First we determine the step locations in the X,Y data. At a given point at location i, we compute the
// difference between three pairs of points: (i,i+1), (i+1,i+2), (i+2,i+3). If the difference in the middle
// is larger than twice the difference on either side, then there is a step at (i+1). Once the step locations
// are found, we find the step values throughout the data and take the median value of all these step values
// as our final step value. This step value is the used to recreate the data value at each step, starting with
// the data value of the first step. We then examine all the data values within each step and look for
// deviations. If any deviation is larger than 1/4 th of the step size, then we reject the data.
//
// Parameter:
// winData: String holding name of users' data worksheet
// ix: Position of X column in the data worksheet
// iy: Position of Y column
// iz: Position of Z column - remember: column numbers start at 0 in OriginC and at 1 in LabTalk
// winTemp: String holding name of temporary worksheet - this worksheet should be created before
// calling this routine, and should have 5 columns in the format XYZYY
// and two more Y columns
//
// Return:
// 0 Cleared for conversion
// 1 Failed when attempting to remove duplicates
// 2 Step determination failed - data not suitable for regular conversion
// 3 x and y datasets not consistent - data not suitable for regular conversion
// 4 Too much deviation within a step - data not suitable for regular conversion
//
////////////////////////////////////////////////////////////////////////////////////
int ConvertRegularXYZ(string winData, int iXCol, int iYCol, int iZCol, string winTemp)
{
//define datasets that map to worksheet data to be converted
Dataset xData(winData, iXCol);
Dataset yData(winData, iYCol);
Dataset zData(winData, iZCol);
// define datasets in temp worksheet and copy raw data over to temp
Dataset mx(winTemp, 0);
Dataset my(winTemp, 1);
Dataset mz(winTemp, 2);
// define datasets to hold median values of groups in X,Y data
Dataset xMedian(winTemp, 3);
Dataset yMedian(winTemp, 4);
//variables
int ii, jj, id, ix, ixblocks, iy, iyblocks;
double dev, xstep, ystep;
// get size of XYZ data set
int isize = mx.GetSize();
// sort temp worksheet wrt X primary, and wrt Y secondary
_LT_Obj
{
sort.wksname$=winTemp;
sort.c1 = 1; // sort only first 3 cols
sort.c2 = 3;
sort.r1 = 1;
sort.r2 = isize;
sort.cname1$ = "A: A";
sort.cname2$ = "A: B";
sort.wks();
}
// determine the location of the first step in X data
ix = FindStep(mx);
if(ix == -1) return 2;
// determine number of groups within X data
ixblocks = isize / ix;
// compute the step values and store them in temporary worksheet
xMedian.SetSize(ixblocks-1);
for(ii = 0; ii < (ixblocks-1); ii++)
{
xMedian[ii] = fabs(mx[ii * ix + ix / 2] - mx[(ii + 1) * ix + ix / 2]);
}
// now sort these step values and pick the median value for the final x step size
_LT_Obj
{
sort.wksname$=winTemp;
sort.c1 = 4; // sort only the 4th col
sort.c2 = 4;
sort.r1 = 1;
sort.r2 = ixblocks-1;
sort.cname1$ = "A: D";
sort.wks();
}
xstep = xMedian[(ixblocks - 1) / 2];
// sort temp worksheet wrt Y primary, and wrt X secondary
_LT_Obj
{
sort.wksname$=winTemp;
sort.c1 = 1; // sort only first 3 cols
sort.c2 = 3;
sort.r1 = 1;
sort.r2 = isize;
sort.cname1$ = "A: B";
sort.cname2$ = "A: A";
sort.wks();
}
// determine the location of the first step in Y data
iy = FindStep(my);
if(iy == -1) return 2;
// determine number of groups within Y data
iyblocks = isize / iy;
// compute the step values and store them in temporary worksheet
yMedian.SetSize(iyblocks-1);
for(ii = 0; ii < (iyblocks-1); ii++)
{
yMedian[ii] = fabs(my[ii * iy + iy / 2] - my[(ii + 1) * iy + iy / 2]);
}
// now sort these step values and pick the median value for the final y step size
_LT_Obj
{
sort.wksname$=winTemp;
sort.c1 = 5; // sort only the 5th col
sort.c2 = 5;
sort.r1 = 1;
sort.r2 = iyblocks-1;
sort.cname1$ = "A: E";
sort.wks();
}
ystep = yMedian[(iyblocks - 1) / 2];
// do a check on whether the x and y data groups agree
// number of groups in one should match group length in the other
if ( (ix!= iyblocks) | (iy!= ixblocks) ) return 3;
// now sort worksheet wrt X, ascending
_LT_Obj
{
sort.wksname$=winTemp;
sort.c1 = 1; // sort only first 3 cols
sort.c2 = 3;
sort.r1 = 1;
sort.r2 = isize;
sort.cname1$ = "A: A";
sort.cname2$ = "A: B";
sort.wks();
}
// now find all the medians of each X group and store them in the temp worksheet
xMedian.SetSize(ixblocks);
for(ii = 0; ii < ixblocks; ii++)
{
xMedian[ii] = mx[ii * ix + ix / 2];
}
//build list of median values for X groups by taking medain value of first
// group and then using the X step value
xMedian.SetSize(ixblocks);
for(ii=0; ii < ixblocks; ii++)
{
xMedian[ii] = mx[ix / 2] + xstep * ii;
}
// now go thru all groups of X data and check for deviations
// replace deviated values with median value for that group
// if a deviation is larger than 1/4 th of step size, data is rejected
for(ii = 0; ii < ixblocks; ii++)
{
for(jj = 0; jj < ix; jj++)
{
id = ii * ix + jj;
dev = fabs(mx[id] - xMedian[ii]);
if(dev >= 0.25 * xstep) return 4;
mx[id] = xMedian[ii];
}
}
// now sort worksheet wrt Y, ascending
_LT_Obj
{
sort.wksname$=winTemp;
sort.c1 = 1; // sort only first 3 cols
sort.c2 = 3;
sort.r1 = 1;
sort.r2 = isize;
sort.cname1$ = "A: B";
sort.cname2$ = "A: A";
sort.wks();
}
// now build list of median values for Y groups by taking medain value of first
// group and then using the average Y step value
yMedian.SetSize(iyblocks);
for(ii=0; ii < iyblocks; ii++)
{
yMedian[ii] = my[iy / 2] + ystep * ii;
}
// now go thru all groups of Y data and check for deviations
// replace deviated values with median value for that group
// if a deviation is larger than 1/4 th of step size, data is rejected
for(ii = 0; ii < iyblocks; ii++)
{
for(jj = 0; jj < iy; jj++)
{
id = ii * iy + jj;
dev = fabs(my[id] - yMedian[ii]);
if(dev >= 0.25 * ystep) return 4;
my[id] = yMedian[ii];
}
}
// now sort the worksheet one last time - deviations in Y values could have
// lead to shuffled order in X data
_LT_Obj
{
sort.wksname$=winTemp;
sort.c1 = 1; // sort only first 3 cols
sort.c2 = 3;
sort.r1 = 1;
sort.r2 = isize;
sort.cname1$ = "A: A";
sort.cname2$ = "A: B";
sort.wks();
}
// operation successful - return 0
return 0;
}
////////////////////////////////////////////////////////////////////////////////////
//
// FindStep:
//
// This function finds the first step location within the Dataset and returns the index of the datapoint
// at the step. If no step is found within the entire dataset, the function returns -1. To find a step,
// three successive differences are examined, and if the difference in the middle is greater than twice
// the difference at the first and the third points, then a step has been found. This algorithm assumes
// that the fluctuations of data points within a group are less than 1/4 th of the step value.
//
////////////////////////////////////////////////////////////////////////////////////
int FindStep(Dataset<double> &v)
{
double step1, step2, step3;
int isize = v.GetSize();
for(int ii=0; ii < (isize-3); ii++)
{
// compute differences at three points
step1 = fabs(v[ii] - v[ii+1]);
step2 = fabs(v[ii+1] - v[ii+2]);
step3 = fabs(v[ii+2] - v[ii+3]);
if((step2 > 2 * step1) && (step2 > 2 * step3)) return ii+2;
}
return -1;
}
// end of all functions in file
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -