Code covered by the BSD License  

Highlights from
CO2gui - lab control and automation

CO2gui - lab control and automation

by

 

06 Jan 2010 (Updated )

Software used for controlling and data logging lab equipment.

prescription=slmset(varargin)
function prescription=slmset(varargin)
% slmset: defines the shape prescription for a model
% usage 1: prescription=slmset(prop1,val1,pro2,val2,...)
% usage 2: prescription=slmset(prescription,prop1,val1,pro2,val2,...)
%
%  A set of property/value pairs are parsed into a structure
%  to use as the prescription for slmengine and slmfit.
% 
% arguments:
%  prop, val - property/value pairs (see below for the complete list)
%          There is no limit on the upper number of property/value
%          pairs allowed.
%          Property names may be shortened, as long as they are
%          unambiguous. Case is ignored.
%
%  prescription - shape prescription structure, defining that
%          which the user is willing to say about the model.
%          The fields of the prescription structure reflect
%          the defaults, plus any modifications specified.
%          This structure will control the behaviours built
%          a curve fit by slmengine or the defaults for slmfit.
%
%
% Property/value pairs:
%
% Properties are character strings, chosen to be mnemonic of their
% purpose. Any property name may be shortened, as long as the
% shortened string is unambiguous. Thus since no other property
% starts with the letter k, any of these alternatives are acceptable
% shortenings for the 'knots' property:  'knot', 'kno', 'kn' or 'k'.
% In the event that a given property is assigned more than once in the
% list of property/value pairs, only the last value in the list is
% assigned.
%
% Property names & admissable values:
%
% 'C2     - Most users want their cubic spline curves to be as
%         smooth and differentiable as possible. For a cubic
%         spline, this is called a twice continuously differentiable
%         function, here simply 'C2'. Of course, if your spline is not
%         cubic, this specification is blithely ignored.
%
%         = 'on' --> Causes the result to be twice differentiable
%           across the knots.
%
%         = 'off' --> Allows a cubic spline to be only C1. The second
%           derivative of the spline MAY have discontinuities across
%           each knot of the spline.
%
%         DEFAULT VALUE:  'on'
%
%         Comment: I would rarely recommend changing this option
%         from the default.
%
% 'concavedown' - controls curvature of the function
%         = 'off'  --> No part of the spline is constrained to be a
%           concave down function (i.e., a negative second derivative.)
%         = 'on' --> f''(x) >= 0 over the entire domain of the spline.
%         = vector of length 2 denoting the start and end points of a
%           region of the spline over which the second derivative is
%           negative.
%         = array of size nx2, each row of which denotes the start and
%           end points of a region of the spline over which the second
%           derivative is negative.
%
%         DEFAULT VALUE:  'off'
%
%         Comment: curvature properties do not apply to piecewise
%         constant functions.
%
% 'concaveup' - controls curvature of the function
%         = 'off'  --> No part of the spline is constrained to be a
%           concave up function (i.e., a positive second derivative.)
%         = 'on' --> f''(x) >= 0 over the entire domain of the spline.
%         = vector of length 2 denoting the start and end points of a
%           region of the spline over which the second derivative is
%           positive.
%         = array of size nx2, each row of which denotes the start and
%           end points of a region of the spline over which the second
%           derivative is positive.
%
%         DEFAULT VALUE:  'off'
%
%         Comment: curvature properties do not apply to piecewise
%         constant functions.
%
% 'constantregion' - defines a region over which the curve is forced
%         be constant, although the exact level is not defined.
%         = [] --> No region of the spline is forced to be a constant
%           function.
%         = vector of length 2 denoting the start and end points of a
%           region of the spline over which it is a constant function.
%         = array of size nx2, each row of which denotes the start and
%           end points of a region of the spline over which it is a
%           constant function.
%
%         DEFAULT VALUE:  []
%
%         Comments: A segment which is forced to be constant over
%         only part of a knot interval must necessarily be constant
%         over that entire interval, since the curve is composed of
%         a single polynomial segment in a knot interval.
%
% 'decreasing' - controls monotonicity of the function
%         = 'off'  --> No part of the spline is constrained to be a
%           decreasing function.
%         = 'on' --> the function will be decreasing over its entire domain.
%         = vector of length 2 --> denotes the start and end points of a
%           region of the curve over which it is monotone decreasing.
%         = array of size nx2 --> each row of which denotes the start
%           and end points of a region of the curve over which it is
%           monotone decreasing.
%
%         DEFAULT VALUE:  'off'
%
%         Comments: in actuality this property should be named
%         'non-increasing', since a constant function is admissible.
%         In addition, it is a sufficient constraint for monotonicity.
%         It is not a necessary constraint. There may exist another
%         spline which has a slightly lower sum of squares and is also
%         monotone.
%
% 'degree' - controls the degree of the piecewise Hermite function
%         = 'constant' --> Use a piecewise constant "Hermite" 
%         = 'linear' --> Use a piecewise linear Hermite 
%         = 'cubic' --> Use a piecewise cubic Hermite 
%         
%         As a concession to memory, valid synonyms for 'constant'
%         'linear', and 'cubic' are respectively the integers 0, 1, & 3
%         
%         DEFAULT: 'cubic'
%
%         Comment: Some properties are inappropriate for all degrees
%         of function. E.g., it would be silly to specify a specific
%         value for the left hand end point slope of a piecewise
%         constant function. All information supplied will be used
%         to whatever extent possible.
%
%         The "order" of a form, as used by the spline toolbox, will
%         be one more than the degree. 'order' is also a valid property
%         in these tools, but it results only in setting the degree
%         field, where degree = order - 1.
%
% 'endconditions' - controls the end conditions applied to the spline
%         = 'natural' --> The "natural" spline conditions will be applied.
%           I.e., f''(x) = 0 at end end of the spline.
%         = 'notaknot' --> Not-a-knot end conditions applied.
%         = 'periodic' --> Periodic end conditions applied.
%         = 'estimate' --> end conditions are estimated from the data.
%
%         DEFAULT VALUE:  'estimate
%
%         Comment: Except for periodicity, end conditions are not
%         relevant to any degree model below cubic.
%
%         Periodic end conditions mean that the function values are
%         the same at each end of the curve for linear and cubic fits.
%
%         For cubic fits, periodicity means that the function has
%         also first and second derivative continuity across the
%         wrapped boundary.
%
%         For piecewise constant fits, end conditions do not apply,
%         and are ignored.
%
% 'envelope' - allows the user to solve for an envelope of the data
%         = 'off' --> the curve will be a simple least squares spline
%         = 'supremum' --> comute a model such that all residuals
%           (yhat - y) are positive. In effect, the curve will be a
%           "supremum" (least upper bound) function.
%         = 'infimum' --> comute a model such that all residuals
%           (yhat - y) are negative. In effect, the curve will be a
%           "infimum" (greatest lower bound) function.
%
%         DEFAULT VALUE:  'off'
%
%         Comment: this option should be rarely used, but its a cute
%         idea when it does come up.
%
% 'errorbar' - defines a set of lower and upper bounds for the function
%         value of the spline at each data point. If there are n data
%         points, then if the corresponding value is:
% 
%         = [] --> No errorbar constraints will be imposed
%         = a scalar E --> error bars will be set at [Y-E,Y+E]
%         = a vector E --> error bars will be set at [Y-E,Y+E]
%         = an nx2 array --> error bars will be set at [Y-E(:,1),Y+E(:,2)]
%
%         DEFAULT VALUE:  []
%
%         Comment: It is possible that depending on the choice of
%         knots, it will be impossible to satisfy some sets of
%         error bars. It may be best to simply use every single data
%         point as a knot. Of course, replicate data points with
%         non-overlappng error bars will always cause a failure.
%
% 'increasing' - controls monotonicity of the function
%         = 'off'  --> No part of the spline is constrained to be an
%           increasing function.
%         = 'on' --> the function will be increasing over its entire domain.
%         = vector of length 2 --> denotes the start and end points of a
%           region of the curve over which it is monotone increasing.
%         = array of size nx2 --> each row of which denotes the start
%           and end points of a region of the curve over which it is
%           monotone increasing.
%
%         DEFAULT VALUE:  'off'
%
%         Comments: in actuality this property should be named
%         'non-decreasing', since a constant function is admissible.
%         In addition, it is a sufficient constraint for monotonicity.
%         It is not a necessary constraint. There may exist another
%         spline which has a slightly lower sum of squares and is also
%         monotone.
%
% 'integral' - known aim value for the integral of the curve over
%         its domain.
%         
%         DEFAULT VALUE:  []
%
% 'interiorknots' - allows for free knot placement (of the interior knots)
%         = 'fixed' 
%           spaced knots. In this case, the first data point will
%           be the first knot.
%         = 'free' --> uses fmincon to optimize the interior knot
%           placement to minimize the overall rmse.
%
%         DEFAULT VALUE:  'fixed'
%
%         Comment: The initial values for the knot placement are
%         taken from the knots property.
%
%         Comment: Since the free knot placement is done by an
%         optimizer (fmincon), it is not allowed to both choose
%         a set of free knots and set the rmse of the fit.
%
%         Comment: The first and last knots are not adjusted by
%         the optimization, so there must be at least 3 knots.
%
%         Comment: Piecewise constant functions sometimes have
%         difficulty with free knots.
%
% 'knots' - controls the number of knots used, or the number of
%           equally spaced knots.
%         = A scalar integer which denotes the number of equally
%           spaced knots. In this case, the first data point will
%           be the first knot.
%         = A vector containing the list of knots themselves.
%           The knots must be distinct. No replicate knots allowed.
%
%         DEFAULT VALUE:  6
%
% 'leftmaxslope' - controls the maximum slope allowed at the left hand
%           end of the curve.
%         = [] --> No explicit value provided for the maximum slope
%           of the spline at its left hand end point.
%         = A numeric scalar --> the slope of the function will be
%           constrained to not rise above this value at its left
%           hand end point (i.e., the first knot.)
%
%         DEFAULT VALUE:  []
% 
% 'leftmaxvalue' - controls the maximum valued allowed at the left hand
%           end of the curve.
%         = [] --> No explicit value provided for the maximum value
%           of the spline at its left hand end point.
%         = A numeric scalar --> the function will be constrained
%           to not rise above this value at its left hand end point
%           (i.e., the first knot.)
%
%         DEFAULT VALUE:  []
%
% 'leftminslope' - controls the minimum slope allowed at the left hand
%           end of the curve.
%         = [] --> No explicit value provided for the minimum slope
%           of the spline at its left hand end point.
%         = A numeric scalar --> the slope of the function will be
%           constrained to not fall below this value at its left
%           hand end point (i.e., the first knot.)
%
%         DEFAULT VALUE:  []
%
% 'leftminvalue' - controls the minimum valued allowed at the left hand
%           end of the curve.
%         = [] --> No explicit value provided for the minimum value
%           of the spline at its left hand end point.
%         = A numeric scalar --> the function will be constrained
%           to not fall below this value at its left hand end point
%           (i.e., the first knot.)
%
%         DEFAULT VALUE:  []
%
% 'leftslope' - controls the function slope at the left hand endpoint.
%         = [] --> No explicit value provided for the slope of the
%           curve at its left hand end point.
%         = A numeric scalar --> the function will be assigned this
%           slope at its left hand end point (i.e., the first knot.)
%
%         DEFAULT VALUE:  []
%
% 'leftvalue' - controls the function value at its left hand endpoint.
%         = [] --> No explicit value provided for the value of the
%           curve at its left hand end point.
%         = A numeric scalar --> the function will be assigned this
%           value at its left hand end point (i.e., the first knot.)
%
%         DEFAULT VALUE:  []
%
% 'linearregion' - defines a region over which the curve is forced
%         be linear, although the exact level is not defined.
%         = [] --> No region of the spline is forced to be a linear
%           function.
%         = vector of length 2 denoting the start and end points of a
%           region of the spline over which it is a linear function.
%         = array of size nx2, each row of which denotes the start and
%           end points of a region of the spline over which it is a
%           linear function.
%
%         DEFAULT VALUE:  []
%
%         Comment 1: A segment which is forced to be linear over
%         only part of a knot interval must necessarily be constant
%         over that entire interval, since the curve is composed of
%         a single polynomial segment in a knot interval.
%         Comment 2: A linear region may extend across knots, in
%         which case the slope will take on the same value across
%         knot boundaries.
%         
% 'maxslope' - controls the globally maximum slope of the function
%         = [] --> No explicit value provided for the globally maximum
%           slope of the curve.
%         = A numeric scalar --> the globally maximum slope of the spline
%
%         DEFAULT VALUE:  []
%
%         Comment: This is a sufficient constraint for the maximum
%         slope of the spline. It is not a necessary constraint.
%         There may exist another spline which has a slightly lower
%         sum of squares and also has the same maximum slope.
%
% 'maxvalue' - controls the globally maximum value of the curve
%         = [] --> No explicit value provided for the globally
%           maximum value of the spline.
%         = A numeric scalar --> the function must lie no higher
%           than this maximum value.
%
%         DEFAULT VALUE:  []
%
%         Comment 1: This constraint is only a necessary constraint.
%         It is not sufficient. In some circumstances the spline may
%         pass slightly above this maximum value
%         Comment 2: The location of the global minimizer is unspecified.
%
% 'minslope' - controls the globally minimum slope of the function
%         = [] --> No explicit value provided for the globally minimum
%           slope of the curve.
%         = A numeric scalar --> the globally minimum slope of the spline
%
%         DEFAULT VALUE:  []
%
%         Comment: This is a sufficient constraint for the minimum
%         slope of the spline. It is not a necessary constraint.
%         There may exist another spline which has a slightly lower
%         sum of squares and also has the same minimum slope.
%
% 'minvalue' - controls the globally minimum value of the curve
%         = [] --> No explicit value provided for the globally
%           minimum value of the spline.
%         = A numeric scalar --> the function will lie no lower
%           than this minimum value.
%
%         DEFAULT VALUE:  []
%
%         Comment 1: This constraint is only a necessary constraint.
%         It is not sufficient. In some circumstances the spline may
%         pass slightly below this minimum value
%         Comment 2: The location of the global minimizer is unspecified.
%
% 'negativeinflection' - controls the existence and placement of a
%           inflection point of the final curve. The second derivative
%           of the function will pass through zero at this point.
%
%         = [] --> no inflection point constraint employed
%         = a numeric scalar --> the function will have a point of
%           inflection at the supplied x location
%
%         DEFAULT VALUE:  []
%
%         Comment: NegativeInflection is really just a composite property
%         of a curve. A negative inflection point at x == a is equivalent
%         to a ConcaveUP function for x<=a, and a ConcaveDown function
%         for x>=a. As such, NegativeInflection will override any other
%         curvature properties one has previously set.
%
%         Comment: Inflection points only apply to linear or cubic models
%
% 'order' - An implicit synonym for 'degree', controls the degree of
%         the piecewise Hermite function. Order MUST be an numeric
%         integer, from the set [1, 2, 4].
%
%         = 1 --> Use a piecewise constant "Hermite" 
%         = 2 --> Use a piecewise linear Hermite 
%         = 4 --> Use a piecewise cubic Hermite 
%         
%         DEFAULT: 4
%
%         Setting the order to some value has the effect of setting
%         the degree of the Hermite spline fit to one less than the
%         order.
%
%         Comment: Some properties are inappropriate for all degrees
%         of function. E.g., it would be silly to specify a specific
%         value for the left hand end point slope of a piecewise
%         constant function. All information supplied will be used
%         to whatever extent possible.
%
% 'plot' - controls whether a final plot is generated of the curve
%         = 'off' --> No plot
%         = 'on' --> plot the curve and data using slmplot 
%         
%         DEFAULT: 'off'
%
% 'positiveinflection' - controls the existence and placement of a
%           inflection point of the final curve. The second derivative
%           of the function will pass through zero at this point.
%
%         = [] --> no inflection point constraint employed
%         = a numeric scalar --> the function will have a point of
%           inflection at the supplied x location
%
%         DEFAULT VALUE:  []
%
%         Comment: PositiveInflection is really just a composite property
%         of a curve. An inflection point at x == a is equivalent to a
%         ConcaveDown function for x<=a, and a ConcaveUp function for
%         x>=a. As such, PositiveInflection will override any other
%         curvature properties one has previously set.
%
%         Comment: Inflection points only apply to linear or cubic models
%
% 'regularization' - 
%         = [] --> Uses the default regularization parameter of 0.0001.
%
%         = A Non-negative scalar value --> explicitly defines the weight
%           given to smoothness of the resulting curve.
%
%         = 'crossvalidation' --> Use cross validation method to choose
%           the regularization parameter.
%
%         = A NEGATIVE scalar value --> attempts to choose a
%           regularization parameter which has as its rmse the absolute
%           value of the supplied value.
%
%         = 'smoothest' --> Finds the smoothest curve that satisfies
%           the supplied prescription. This is not really a least
%           squares model, since the goal is purely to maximize the
%           smoothness. This option would very often be used in
%           conjunction with errorbars.
%
%         DEFAULT VALUE:  0.0001
%
%         Comment: Smaller values will yield less smoothing, larger
%         values more smoothing. In most cases this parameter should
%         be left alone. It is used to prevent numerical singularities
%         in the linear algebra, as well as help in the case of
%         extrapolation and intrapolation. Smoothness of the resulting
%         spline can be far better controlled by changing the number
%         of knots and their placement. Specifically, the regularization
%         parameter is a scale factor applied to the integral of the
%         squared second derivative of the spline.
%
%         Comment: It is possible that no value for the regularization
%         parameter will yield the given rmse. In this case the sky will
%         fall down.
%
%         Comment: Since the cross validation option and matching a
%         given rmse are both optimizations, it is not allowed to use
%         these options together with the interiorknots estimation.
%
%         Comment: Both the cross validation and rmse options can
%         both be quite slow. Remember that they are optimizations.
%
% 'result' - controls the output structure style
%         = 'pp'  --> Returns a pp struct, use ppval to evaluate
%         = 'slm' --> Returns a slm struct in a Hermite form. Evaluate
%         using slmeval.
%
%         DEFAULT VALUE:  'slm'
%
% 'rightmaxslope' - controls the maximum slope allowed at the right
%           hand end of the curve.
%         = [] --> No explicit value provided for the maximum slope
%           of the spline at its right hand end point.
%         = A numeric scalar --> the slope of the function will be
%           constrained to not rise above this value at its right
%           hand end point (i.e., the last knot.)
%
%         DEFAULT VALUE:  []
% 
% 'rightmaxvalue' - controls the maximum valued allowed at the right
%           hand end of the curve.
%         = [] --> No explicit value provided for the maximum value
%           of the spline at its right hand end point.
%         = A numeric scalar --> the function will be constrained
%           to not rise above this value at its right hand end point
%           (i.e., the first knot.)
%
%         DEFAULT VALUE:  []
%
% 'rightminslope' - controls the minimum slope allowed at the right
%           hand end of the curve.
%         = [] --> No explicit value provided for the minimum slope
%           of the spline at its right hand end point.
%         = A numeric scalar --> the slope of the function will be
%           constrained to not fall below this value at its right
%           hand end point (i.e., the last knot.)
%
%         DEFAULT VALUE:  []
%
% 'rightminvalue' - controls the minimum valued allowed at the right
%           hand end of the curve.
%         = [] --> No explicit value provided for the minimum value
%           of the spline at its right hand end point.
%         = A numeric scalar --> the function will be constrained
%           to not fall below this value at its right hand end point
%           (i.e., the last knot.)
%
%         DEFAULT VALUE:  []
%
% 'rightslope' - controls the function slope at the right hand endpoint.
%         = [] --> No explicit value provided for the slope of the
%           curve at its right hand end point.
%         = A numeric scalar --> the function will be assigned this
%           slope at its right hand end point (i.e., the last knot.)
%
%         DEFAULT VALUE:  []
%
% 'rightvalue' - controls the function value at its right hand endpoint.
%         = [] --> No explicit value provided for the value of the
%           curve at its right hand end point.
%         = A numeric scalar --> the function will be assigned this
%           value at its right hand end point (i.e., the last knot.)
%
%         DEFAULT VALUE:  []
%
% 'scaling' - controls data scaling to avoid numerical problems
%         = 'on' --> data is shifted and scaled so as to minimize
%           any numerical problems that may result in the solution.
%         = 'off' --> No scaling is done.
%
%         DEFAULT VALUE:  'on'
%
%         Comments: There is no scaling that will positively
%         eliminate all problems. All scaling is undone in the
%         final spline coefficients.
%
% 'simplepeak' - controls the existence and placement of a single
%           maximizer of the final curve
%
%         = [] --> no peak placement constraint employed
%         = a numeric scalar --> the function will attain its maximum
%           at the supplied x location
%
%         DEFAULT VALUE:  []
%
%         Comment: SimplePeak is really just a composite property of
%         a curve. A peak at x == a is equivalent to a monotone increasing
%         function for x<=a, and a monotone decreasing function for
%         x>=a. As such, simplepeak will override any other monotonicity
%         properties one has previously set.
%
% 'simplevalley' - controls the existence and placement of a single
%           minimizer of the final curve
%
%         = [] --> no valley placement constraint employed
%         = a numeric scalar --> the function will attain its minimum
%           at the supplied x location
%
%         DEFAULT VALUE:  []
%
%         Comment: SimpleValley is really just a composite property
%         of a curve. A valley at x == a is equivalent to a monotone
%         decreasing function for x<=a, and a monotone increasing
%         function for x>=a. As such, simplevalley will override any
%         other monotonicity properties one has previously set.
%
% 'verbosity' - controls commandline feedback to the user
%         = 0 --> No response at the commandline
%         = 1 --> Fit statistics reported
%         = 2 --> Debug level output
%         
%         DEFAULT: 0
%
% 'weights' - defines a weight vector 
%         = [] --> all data points are assigned equal (unit) weight.
%         = vector of the same length as length(x), denotes relative
%           weights for each data point. If supplied, the length of
%           this vector of weights must be the same as the number of
%           data points.
%
%         DEFAULT VALUE:  []
%
% 'xy'  - Forces the curve through an individual point or set of points
%         = [] --> no points are forced
%         = a 1x2 vector --> an x-y pair that the curve must pass
%           through with no error.
%         = an nx2 array --> each row corresponds to a single point
%           that the curve passes through.
%         
%         DEFAULT: []
%
%         Comment 1: The curve will pass through the desired point
%         to within computational error, IF it is possible to do so.
%         Comment 2: Multiple points that are inconsistent with each
%         other, or inconsistent with other parameters that are set
%         will cause failure of the least squares.
%
% 'xyp'  - Forces the curve to have a specified slope at an individual
%         point or set of points
%         = [] --> no points have their slope enforced
%         = a 1x2 vector --> an x-yprime pair that the curve must
%           satisfy through with no error.
%         = an nx2 array --> each row corresponds to an x-yprime
%           pair that the curve must satisfy.
%         
%         DEFAULT: []
%
%         Comment 1: The curve will satisfy the desired slope to
%         within computational error, IF it is possible to do so.
%         Comment 2: Multiple points that are inconsistent with each
%         other, or inconsistent with other parameters that are set
%         will cause failure of the least squares.
%         Comment 3: Setting the slope at some point of a zero'th
%         degree function will be ignored.
%
% 'xypp' - Forces the curve to have a specified second derivative
%         at an individual point or set of points
%         = [] --> no points have their 2nd derivative enforced
%         = a 1x2 vector --> an x-y'' pair that the curve must
%           satisfy through with no error.
%         = an nx2 array --> each row corresponds to an x-y''
%           pair that the curve must satisfy.
%         
%         DEFAULT: []
%
%         Comment: The curve will satisfy the desired 2nd derivative
%         to within computational error, IF it is possible to do so.
%         Comment: Multiple points that are inconsistent with each
%         other, or inconsistent with other parameters that are set
%         will cause failure of the least squares.
%         Comment: Setting the 2nd derivative at some point of a
%         zero'th degree or linear function will be ignored.
%         Comment: This property only applies to cubic models.


% was an initial prescription struct provided?
if (nargin==0) || ~isstruct(varargin{1})
  % defaults for all properties
  prescription.C2 = 'on';
  prescription.ConcaveDown = 'off';
  prescription.ConcaveUp = 'off';
  prescription.ConstantRegion = [];
  prescription.Decreasing = 'off';
  prescription.Degree = 3;
  prescription.EndConditions = 'estimate';
  prescription.Envelope = 'off';
  prescription.ErrorBar = [];
  prescription.Increasing = 'off';
  prescription.Integral = [];
  prescription.InteriorKnots = 'fixed';
  prescription.Knots = 6;
  prescription.LeftMaxSlope = [];
  prescription.LeftMaxValue = [];
  prescription.LeftMinSlope = [];
  prescription.LeftMinValue = [];
  prescription.LeftSlope = [];
  prescription.LeftValue = [];
  prescription.LinearRegion = [];
  prescription.MaxSlope = [];
  prescription.MaxValue = [];
  prescription.MinSlope = [];
  prescription.MinValue = [];
  prescription.NegativeInflection = [];
  prescription.Order = [];
  prescription.Plot = 'off';
  prescription.PositiveInflection = [];
  prescription.Regularization = 0.0001;
  prescription.Result = 'slm';
  prescription.RightMaxSlope = [];
  prescription.RightMaxValue = [];
  prescription.RightMinSlope = [];
  prescription.RightMinValue = [];
  prescription.RightSlope = [];
  prescription.RightValue = [];
  prescription.Scaling = 'on';
  prescription.SimplePeak = [];
  prescription.SimpleValley = [];
  prescription.Verbosity = 0;
  prescription.Weights = [];
  prescription.XY = [];
  prescription.XYP = [];
  prescription.XYPP = [];
elseif isstruct(varargin{1})
  % there is a struct provided. use it for defaults
  prescription = varargin{1};
  varargin(1)=[];
end

% begin processing property/value pairs
if isempty(varargin)
  % just use the defaults already present in prescription
else
  prescription = parse_pv_pairs(prescription,varargin);
end

% check that all properties were set, also check
% for some simple errors

% C2 must be: 'off', 'on', or ''
prescription = value_check(prescription,'C2', ...
   {'off' 'on'},[],0);

% ConcaveDown must be: 'off', 'on', an nx2 array
prescription = value_check(prescription,'ConcaveDown', ...
   {'off' 'on'},{[NaN,2]},0);
if (ischar(prescription.ConcaveDown) && ...
    strcmp(prescription.ConcaveDown,'on')) || ...
   (isnumeric(prescription.ConcaveDown) && ...
   ~isempty(prescription.ConcaveDown))
  % 
  % override any prior inflection point settings
  prescription.PositiveInflection = [];
  prescription.NegativeInflection = [];
  
end

% ConcaveUp must be: 'off', 'on', an nx2 array
prescription = value_check(prescription,'ConcaveUp', ...
   {'off' 'on'},{[NaN,2]},0);
if (ischar(prescription.ConcaveUp) && ...
    strcmp(prescription.ConcaveUp,'on')) || ...
   (isnumeric(prescription.ConcaveUp) && ...
   ~isempty(prescription.ConcaveUp))
  % 
  % override any prior inflection point settings
  prescription.PositiveInflection = [];
  prescription.NegativeInflection = [];
  
end

% ConstantRegion must be: [], or an nx2 array
prescription = value_check(prescription,'ConstantRegion', ...
   {},{[NaN,2]},1);

% Decreasing must be: 'off', 'on', or an nx2 array
prescription = value_check(prescription,'Decreasing', ...
   {'off' 'on'},{[NaN,2]},0);
if (ischar(prescription.Decreasing) && ...
    strcmp(prescription.Decreasing,'on')) || ...
   (isnumeric(prescription.Decreasing) && ...
   ~isempty(prescription.Decreasing))
  % 
  % override any prior peak or valley settings
  prescription.SimplePeak = [];
  prescription.SimpleValley = [];
  
end

% EndConditions must be: 'natural', 'notaknot', 'periodic' 'estimate'
prescription = value_check(prescription,'EndConditions', ...
   {'natural', 'notaknot', 'periodic' 'estimate'},{},0);

% Envelope must be: 'off', 'supremum', 'infinmum'
prescription = value_check(prescription,'Envelope', ...
   {'off' 'supremum' 'infimum'},{},0);
 
% ErrorBar must be: [], scalar, vector, or an nx2 array
prescription = value_check(prescription,'ErrorBar', ...
     {},{[1 1] [NaN 1] [1 NaN] [NaN 2]},1);

% InteriorKnots must be: 'fized', 'free'
prescription = value_check(prescription,'InteriorKnots', ...
   {'fixed', 'free'},{},0);

% Increasing must be: 'off', 'on', or an nx2 array
prescription = value_check(prescription,'Increasing', ...
   {'off' 'on'},{[NaN,2]},0);
if (ischar(prescription.Increasing) && ...
    strcmp(prescription.Increasing,'on')) || ...
   (isnumeric(prescription.Increasing) && ...
   ~isempty(prescription.Increasing))
  % 
  % override any prior peak or valley settings
  prescription.SimplePeak = [];
  prescription.SimpleValley = [];
  
end

% Integral must be a numeric scalar or empty
prescription = value_check(prescription,'Integral', ...
   {},{[1 1]},1);

% Knots must be a numeric scalar or a vector
prescription = value_check(prescription,'Knots', ...
   {},{[1 1], [NaN,1], [1,NaN]},0);

% LeftMaxSlope must be a numeric scalar or empty
prescription = value_check(prescription,'LeftMaxSlope', ...
   {},{[1 1]},1);

% LeftMaxValue must be a numeric scalar or empty
prescription = value_check(prescription,'LeftMaxValue', ...
   {},{[1 1]},1);

% LeftMinSlope must be a numeric scalar or empty
prescription = value_check(prescription,'LeftMinSlope', ...
   {},{[1 1]},1);

% LeftMinValue must be a numeric scalar or empty
prescription = value_check(prescription,'LeftMinValue', ...
   {},{[1 1]},1);

% LeftSlope must be a numeric scalar or empty
prescription = value_check(prescription,'LeftSlope', ...
   {},{[1 1]},1);

% LeftValue must be a numeric scalar or empty
prescription = value_check(prescription,'LeftValue', ...
   {},{[1 1]},1);

% LinearRegion must be: [], or an nx2 array
prescription = value_check(prescription,'LinearRegion', ...
   {},{[NaN,2]},1);

% MaxSlope must be a numeric scalar or empty
prescription = value_check(prescription,'MaxSlope', ...
   {},{[1 1]},1);

% MaxValue must be a numeric scalar or empty
prescription = value_check(prescription,'MaxValue', ...
   {},{[1 1]},1);

% MinSlope must be a numeric scalar or empty
prescription = value_check(prescription,'MinSlope', ...
   {},{[1 1]},1);

% MinValue must be a numeric scalar or empty
prescription = value_check(prescription,'MinValue', ...
   {},{[1 1]},1);

% NegativeInflection must be a numeric scalar or empty
prescription = value_check(prescription,'NegativeInflection', ...
   {},{[1 1]},1);
if ~isempty(prescription.NegativeInflection)
  % override any prior curvature settings
  prescription.ConcaveUp = 'off';
  prescription.ConcaveDown = 'off';
  prescription.PositiveInflection = [];
end

% Degree must be: 'constant', 'linear', 'cubic', or 0, 1, 3
prescription = value_check(prescription,'Degree', ...
   {'constant' 'linear', 'cubic' '0', '1', '3'},{[1 1]},0);
switch prescription.Degree
case {'constant' '0' 0}
  prescription.Degree = 0;
case {'linear' '1' 1}
  prescription.Degree = 1;
case {'cubic' '3' 3}
  prescription.Degree = 3;
otherwise
  error 'degree may be any of: {0,1,3, ''constant'', ''linear'', ''cubic''}'
end

% Order must be: 1, 2, 4
prescription = value_check(prescription,'Order', ...
   {'1', '2', '4'},{1 2 4},1);
if isempty(prescription.Order)
  % Do not override Degree, already defined.
else
  switch prescription.Order
    case {'1' 1}
      prescription.Degree = 0;
    case {'2' 2}
      prescription.Degree = 1;
    case {'4' 4}
      prescription.Degree = 3;
    otherwise
      error('Order may be any of: {[],1,2,4}')
  end
end

% Plot must be: 'off', 'on' 
prescription = value_check(prescription,'Plot', ...
   {'off' 'on'},{},0);

% PositiveInflection must be a numeric scalar or empty
prescription = value_check(prescription,'PositiveInflection', ...
   {},{[1 1]},1);
if ~isempty(prescription.PositiveInflection)
  % override any prior curvature settings
  prescription.ConcaveUp = 'off';
  prescription.ConcaveDown = 'off';
  prescription.NegativeInflection = [];
end

% Regularization must be: 'crossvalidation', 'smoothest', or a numeric scalar
prescription = value_check(prescription,'Regularization', ...
   {'crossvalidation' 'smoothest'},{[1 1]},0);
 
% Result must be: 'pp', 'slm', or []
prescription = value_check(prescription,'Result', ...
   {'pp' 'slm'},{},0);

% RightMaxSlope must be a numeric scalar or empty
prescription = value_check(prescription,'RightMaxSlope', ...
   {},{[1 1]},1);

% RightMaxValue must be a numeric scalar or empty
prescription = value_check(prescription,'RightMaxValue', ...
   {},{[1 1]},1);

% RightMinSlope must be a numeric scalar or empty
prescription = value_check(prescription,'RightMinSlope', ...
   {},{[1 1]},1);

% RightMinValue must be a numeric scalar or empty
prescription = value_check(prescription,'RightMinValue', ...
   {},{[1 1]},1);

% RightSlope must be a numeric scalar or empty
prescription = value_check(prescription,'RightSlope', ...
   {},{[1 1]},1);

% RightValue must be a numeric scalar or empty
prescription = value_check(prescription,'RightValue', ...
   {},{[1 1]},1);

% Scaling must be: 'off', 'on'
prescription = value_check(prescription,'Scaling', ...
   {'off' 'on'},{},0);

% SimplePeak must be a numeric scalar or empty
prescription = value_check(prescription,'SimplePeak', ...
   {},{[1 1]},1);
if ~isempty(prescription.SimplePeak)
  % override any prior monotonicity settings
  prescription.Decreasing = 'off';
  prescription.Increasing = 'off';
  prescription.SimpleValley = [];
end

% SimpleValley must be a numeric scalar or empty
prescription = value_check(prescription,'SimpleValley', ...
   {},{[1 1]},1);
if ~isempty(prescription.SimpleValley)
  % override any prior monotonicity settings
  prescription.Decreasing = 'off';
  prescription.Increasing = 'off';
  prescription.SimplePeak = [];
end

% Verbosity must be 0 or 1(small talk) or 2(garrulous)
prescription = value_check(prescription,'Verbosity', ...
   {},{[1 1]},0);

% Weights must be a vector or empty
prescription = value_check(prescription,'Weights', ...
   {},{[NaN 1] [1 NaN]},1);

% XY must be an nx2 array or empty
prescription = value_check(prescription,'XY', ...
   {},{[NaN 2]},1);

% XYP must be an nx2 array or empty
prescription = value_check(prescription,'XYP', ...
   {},{[NaN 2]},1);

% XYPP must be an nx2 array or empty
prescription = value_check(prescription,'XYPP', ...
   {},{[NaN 2]},1);



% ======================================================
% =========== begin value_check subfunction ============
% ======================================================
function prescription=value_check(prescription,fieldname,legalchar,legalnumeric,legalempty)
% checks that:
% 1. the field exists
% 2. it contains an acceptable character string or a
%    numeric array of valid shape for this field

% first test that the field exists
if ~isfield(prescription,fieldname)
  error(['Field not found: ',fieldname])
end

% grab that field
Field = getfield(prescription,fieldname);

% is an empty array a legal option?
if isempty(Field) && ~legalempty
  error(['Empty array is not legal for this field ',fieldname])
end

% if its a character string, is it a legal option?
if ischar(Field)
  if ~isempty(legalchar)
    Field = lower(Field);
    ind = strmatch(Field,legalchar);
    if isempty(ind)
      error(['Illegal value for ',fieldname,', see help slmset'])
    elseif length(ind)>1
      error(['Ambiguous value for ',fieldname,', see help slmset'])
    else
      prescription = setfield(prescription,fieldname,legalchar{ind});
    end
  else
    error(['Char is not legal for: ',fieldname,', see help slmset'])
  end
end

% is a numeric array a legal value?
if isnumeric(Field)
  if isempty(legalnumeric)&&~isempty(Field)
    error(['Numeric is not legal for this field ',fieldname])
  else
    % we've already checked about empty fields
    s = size(Field);
    for i=1:length(legalnumeric)
      % verify that the size of Field fits one of the
      % legal size templates in legalnumeric
      
      
      
      
      
      
      
      
      
      
    end
  end
end



Contact us