class_docstr: Bsplines of a given order and specified knots.
  
  Implementation is based on description in Chapter 5 of
  
  Hastie, Tibshirani and Friedman (2001). "The Elements of Statistical
  Learning." Springer-Verlag. 536 pages.
  
  
  INPUTS:
     knots  -- a sorted array of knots with knots[0] the lower boundary,
               knots[1] the upper boundary and knots[1:-1] the internal
               knots.
     order  -- order of the Bspline, default is 4 which yields cubic
               splines
     M      -- number of additional boundary knots, if None it defaults
               to order
     coef   -- an optional array of real-valued coefficients for the Bspline
               of shape (knots.shape + 2 * (M - 1) - order,).
     x      -- an optional set of x values at which to evaluate the
               Bspline to avoid extra evaluation in the __call__ method
class_docstr_tok: ["Bsplines","of","a","given","order","and","specified","knots",".","Implementation","is","based","on","description","in","Chapter","5","of","Hastie",",","Tibshirani","and","Friedman","(","2001",")",".","``","The","Elements","of","Statistical","Learning",".","''","Springer-Verlag",".","536","pages",".","INPUTS",":","knots","--","a","sorted","array","of","knots","with","knots","[","0","]","the","lower","boundary",",","knots","[","1","]","the","upper","boundary","and","knots","[","1",":","-1","]","the","internal","knots",".","order","--","order","of","the","Bspline",",","default","is","4","which","yields","cubic","splines","M","--","number","of","additional","boundary","knots",",","if","None","it","defaults","to","order","coef","--","an","optional","array","of","real-valued","coefficients","for","the","Bspline","of","shape","(","knots.shape","+","2","*","(","M","-","1",")","-","order",",",")",".","x","--","an","optional","set","of","x","values","at","which","to","evaluate","the","Bspline","to","avoid","extra","evaluation","in","the","__call__","method"]
code: def __init__(self, knots, order=4, M=None, coef=None, x=None):
      knots = np.squeeze(np.unique(np.asarray(knots)))
  
      if knots.ndim != 1:
          raise ValueError("expecting 1d array for knots")
  
      self.m = order
      if M is None:
          M = self.m
      self.M = M
  
      self.tau = np.hstack(
          [[knots[0]] * (self.M - 1), knots, [knots[-1]] * (self.M - 1)]
      )
  
      self.K = knots.shape[0] - 2
      if coef is None:
          self.coef = np.zeros(
              (self.K + 2 * self.M - self.m), np.float64
          )
      else:
          self.coef = np.squeeze(coef)
          if self.coef.shape != (self.K + 2 * self.M - self.m):
              raise ValueError(
                  "coefficients of Bspline have incorrect shape"
              )
      if x is not None:
          self.x = x
  
imports: import numpy
  import numpy.linalg
  from scipy.linalg import solveh_banded
  from scipy.optimize import golden
  from models import _hbspline
  import warnings
label_desc: Use image node_id 1 to create a new BSpline object  with example: obj = BSpline(knots, order, M, coef, x)