.. highlightlang:: us .. _filter-functions-for-xy-datasets: Filter Functions for XY datasets ================================ Filter functions are new with UniPlot 4.0. They offer more possibilities to filter and transform the original data of a dataset. A filter, for example, can calculate a cubic spline or remove unwanted points from a curve. They are stored inside the dataset. Filter functions are recalculated when the original data is edited or the datasource of a dataset has changed. The filter functions can be specified for XY datasets (1D or 2D). When a dataset is plotted, the result of the filter function is displayed in the diagram. Optionally, the original data can be plotted as symbols. For each dataset a list of filter functions can be specified. The first function will use the original data as its input. All other functions will use the output of the previous filter function. The results of the filter functions are saved in the dataset. If you pass a UniPlot document with filtered datasets to another UniPlot user the result will be displayed correctly, but recalculation of the filter function is only possible if the filter function used in the document are available on the computer. Filter functions are UniScript functions which can be defined by the user. The following functions can be used as a template for your own filter functions. For more information on writing filter function, move to the bottom of this help topic. .. _list-of-filter-functions: List of filter functions ------------------------ The source code of the following functions can be found in :file:`script/rs_xy_filt_funcs.ic`. abs ^^^ :: abs() abs() returns the absolute value. bit ^^^ Extracts a bit form a vector. iBit in the range 1 to 64. The data can be scaled. :: bit(iBit, rsScaleFactor, rsScaleOffset) iBit: Range 1 to 64 Scaling: y = rsScaleFactor * bitValue + rsScaleOffset If *rsScaleFactor* is set to 1 and *rsScaleOffset* is set to 0, the result is in the range 0 to 1. min ^^^ :: min() Calulates the minimum of all given y values. max ^^^ :: max() Calulates the maximum of all given y values. mean ^^^^ :: mean() Calulates the mean value of all given y values. median ^^^^^^ :: median(nPercent) Calculates the median of all given y values. Sorts the data in ascending order and picking the middle one if nPercent == 50 percent. The index of the data point can be specified in percent of the number of data points. smooth ^^^^^^ :: smooth() smooth(nNeighbor) Smooth a dataset with the moving average. The optional parameter ``nNeighbor`` specifies the number of points used the moving average. *nNeighbor* specifies the window width. The window width is ``2 * nNeighbor + 1``. The If the parameter is not specified, it is set to 10. With the help of the optional parameter ``PeakFilterFactor`` peaks can be keept in the filtered signal. If set to 0 all peaks are smoothed. This is how the Peak-Filter works: * The smooth function will be applied on the original data. * The difference between the original and the filtered data is calculated. * The difference is multiplied with `PeakFilterFactor (Range 0 to 1) = dy`. * All points of the original data with a difference greater than dy are inserted into the filtered signal. .. _smooth_median: smooth_median ^^^^^^^^^^^^^ :: smooth_median(nNeighbor) Running median. nNeighbor is the window size of the moving window in the range 3 to 1025. Even numbers will be rounded up to the next odd number. For each window the middle value found is used. The filter can be used to reduce random noise and spikes. (see :ref:`moving_median`). Example: ``smooth_median(5)`` 5 consecutive points are sorted ascending and the third point is used. For a window size of 5, the first 2 point and the last 2 points are not altered. given: ``[5, 7, 6, 4, 27, 8, 4, 5]`` result: ``[5, 7, 6, 7, 6, 8, 4, 5]`` Example: .. image:: S:/uniplot-obj/images/peaks.* smooth_golay (Savitzky-Golay) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ :: smooth_golay(nPolynomialOrder, nWindowSize) smooth_golay(nPolynomialOrder, nWindowSize, PeakFilterFactor) A better procedure than simply averaging points is to perform a least squares fit of a small set of consecutive data points to a polynomial and take the calculated central point of the fitted polynomial curve as the new smoothed data point. The smoothing effect of the Savitzky-Golay algorithm is not so aggressive as in the case of the moving average and the loss and/or distortion of vital information is comparatively limited. .. image:: S:/uniplot-obj/images/savitzky-golay.* Peak-Filter. The method is identical to the smooth-funcition. .. image:: S:/uniplot-obj/images/savitzky-golay-peak-filter.* spline ^^^^^^ :: spline() spline(nPoints) Calculates a cubic spline that will cross all datapoints. nPoints: Number of spline points (Default = 1000). The number must be in the range of 10 to 100000. fitspline ^^^^^^^^^ :: fit_spline() fit_spline(smoothfactor) fit_spline(smoothfactor, nPoints) The Fit Spline function fits a smoothing spline using a smoothing parameter you specify. smoothfactor: A value of 0 meas no smoothing (i.e. the spline will cross all original data points) and a value greater as 0 will create a smooting spline. nPoints: Number of points in the range 10 to 100000. akimaspline ^^^^^^^^^^^ :: akimaspline() akimaspline(nPoints) Akima spline interpolation better copes with discontinuities in a time series than normal cubic splines. The interpolation approximates a manually drawn curve better than the ordinary splines, but the second derivation is not continuous. nPoints: Number of spline points in the range 10 to 100000. .. index:: Regression Line .. _polyfit-filter: polyfit ^^^^^^^ :: polyfit() polyfit(polynomOrder) polyfit(polynomOrder, nPoints, nInfoText) polyfit(polynomOrder, nPoints, nInfoText, xMin, xMax) Polynomial curve fitting. polyfit finds the coefficients of a polynomial p(x) of degree n that fits the data, p(x(i)) to y(i), in a least squares sense. Creates a fit polynom of degree 0 to 9. The polynomial of degree 1 is the regression line. polynomOrder: Order of polynom (default = 1). 1 creates a straight line (linear regression). nPoints: Number of points of the fitting curve (default = 1000). The number of points should be in the range 2 to 100000. nInfoText: 0 = no text, 1 = Polynom parameter, 2 = Polynom parameter and R2 (coefficient of determination). xMin: Start value, can be smaller than the first x-data value. If set to 1e10, the x-minimum of the dataset will be used. xMax: End value, can be larger than the last x-data value. If set to 1e10, the x-maximum of the dataset will be used. interpol ^^^^^^^^ :: interpol() interpol(nPoints) Calculates extra points for a curve through linear interpolation. nPoints: Number of points of the new curve or a list of x-coordinates separated by a comma. interpol2 ^^^^^^^^^ :: interpol2(xmin, xmax, xdelta) Calculates extra points for a curve from xmin to xmax with an increment of xdelta through linear interpolation. The dataset must be monoton. If xmin or xmax is out of x-range the range will be corrected. The function cannot perform an extrapolation. sort ^^^^ :: sort() Sorts the data in ascending order based on the x coordinate. simplify ^^^^^^^^ :: simplify() simplify(nTolerance) Polyline simplification using the Douglas-Peucker algorithm. nTolerance: Specified the maximum distance between the original curve and the simplified curve. A value of 1 sets a tolerance of 10%. The values 2,3,4,5, etc. always divide the tolerance by 2. Therfore a value of 4 is a tolerance of 1.25%. A value of 30 sets a tolerance of almost 0% Default value is 5. .. image:: S:/uniplot-obj/images/filter-simplify.* boundary ^^^^^^^^ :: boundary() boundary(type) boundary(type, width) Calculates the upper, lowert or upper and lower hull curve. type: 0 - upper hull (Default value = 0). type: 1 - lower hull. type: 2 - upper and lower hull. width: Class width in percent (Default value = 5%). step ^^^^ :: step() step(nType) Calculates a cityscape or skyline curve nType: 0 - Curve starts horizontal. nType: 1 - Curve starts vertical (Default value = 1). integrate ^^^^^^^^^ :: integrate() Calculates the integral curve using the trapezoidal method. integrate_cycle ^^^^^^^^^^^^^^^ :: integrate_cycle(xCycleLength, xCycleStart, nCycle) Calculates for each cycle the integral curve using the trapezoidal method. xCycleLength: Length of a cycle in x-coordinates, example: 0.2s or 720 °CA. xCycleStart: First Point in x-coordinates, example 0s or -360 °CA. xCycleStart is set to x[1] if less than x[1]. nCycle: Number of Cycles. 0 for all cycles. cycle_value ^^^^^^^^^^^ :: cycle_value(nType, xCycleLength, xCycleStart, nCycle) Calculates one of the following values for each cycle: nType: 1: Mean Value, 2: Max Value, 3: Min Value xCycleLength: Length of a cycle in x-coordinates, example: 0.2s or 720 °CA. xCycleStart: First Point in x-coordinates, example 0s or -360 °CA. xCycleStart is set to x[1] if less than x[1]. nCycle: Number of Cycles. 0 for all cycles. differentiate ^^^^^^^^^^^^^ :: differentiate() Calculates the derivative. extract ^^^^^^^ :: extract(xmin, xmax) Extracts data from a curve in the range xmin to xmax. The points at the lower and upper limit are calculated by linear interpolation. The x-coordinates must be strictly increasing. see extract_points extract_points ^^^^^^^^^^^^^^ :: extract_points(imin, imax) The extract_points function extracts the points from imin to imax. imin: First point (imin >= 1 and <= Number of points - 2). imax: Last point. If imax is negative the points are counted starting from the end. Example for a dataset with 17 points: extract_points(1,22) equivalent to extract_points(1,17) extract_points(1,-1) equivalent to extract_points(1,17) extract_points(1,0) equivalent to extract_points(1,17) extract_points(3,-3) equivalent to extract_points(3,15) find ^^^^ :: find(min, max, Axis, Type) Returns data points in the range min to max. If no data point is found the functions returns the value 0. Axis is one of the following values: 1: Search x-coordinates 2: Search y-coordinates Type is one of the followin values: 0: Absolute values (no scaling) 1: Relative values: Values are divided by the maximum before the search (xy / xymax). 2: Relative values: Valurs are scaled to the range 0 to 1: (xy - xymin) / (xymax-xymin). If Type is 1 or 2 min and max should be set in the range 0 to 1 Example: To find all y-data points in the range 90% of the maximum value, the filter string would be find(0.9, 1.0, 2, 1). remove_duplicate_points ^^^^^^^^^^^^^^^^^^^^^^^ :: remove_duplicate_points() Removes all duplicate consecutive datapoints with equal x coordinates except the first data point. .. _correction_factor: correction_factor ^^^^^^^^^^^^^^^^^ :: correction_factor(x,y) Corrects the y-coordinate using a variable correction factor. .. _writing-filter-functions: Writing Filter Functions ------------------------ Below is an example on how to write filter functions :: def _xy_filter_func_scale(hData, a, b) { if (nargsin() == 1) { _a = 1; _b = 0; } else if (nargsin() == 2) { _a = a; _b = 0; } else if (nargsin() == 3) { _a = a; _b = b; } xy = XYGetData(hData); x = xy[;1]; y = xy[;2]; y = _a * y + _b; return XYSetData(hData, x, y, TRUE); // Don't forget the TRUE! } def _xy_filter_info_scale() { svInfo = ["Y-Skalierung"; "scale(a,b)\n\nScales the y-coordinates with the help" + .... "of the equation y = a*y + b"; ""; "2"; "Factor a:1:-1e9:1e9"; "Offset b:0:-1e9:1e9"]; return svInfo; } To define a new filter function, two functions need to be written. One function calculates the data, the other provides information to the user interface. In the example above these two functions are ``_xy_filter_func_scale`` and ``_xy_filter_info_scale``. The filter function names begin with ``_xy_filter_func_``, followed by the functions user namen in this case ``scale``. The functions can be saved in a file with en extension :file:`.ic` in UniPlot's autoload directory. When UniPlot is started the functions will be loaded automatically. The info function returns a string vector with at least 4 elements: .. list-table:: :header-rows: 1 * - Element - Meaning * - svInfo[1] - Function name. * - svInfo[2] - Info text shown in the Help windows. If the text is long it can be spaced over various lines as in the example. The rows will be linked with ``+ ....``. * - svInfo[3] - Not used. Must be an empty string (""). * - svInfo[4] - Number of parameters "0" to "8" * - svInfo[5,6,..] - (Optional) Parameter name, default value and range separated by a colon (:). The func function makes the calculation. The dataset handle will always be the first parameter. Data from the dataset can be accessed using the handle (:ref:`XYGetData`). The results will be written with the :ref:`XYSetData` function. The other parameters are option and must match the definition in the info function. .. us.history **History** .. list-table:: :header-rows: 1 * - Version - Description * - R2022.2 - `correction_factor`_ :sub:`id-1866448`