Beispiel #1
0
  def __init__(self, Tol = 1.e-6, Iter = 200, K = 10, N = 6,\
      Lc = 2.0, refl_s = 0.0, F = np.pi, Beta=.0, sun0_zen = 180.,\
      sun0_azi = 0.0, arch = 'u', ln = 1.2, cab = 30., car = 10., \
      cbrown = 0., cw = 0.015, cm = 0.009, lamda = 760, refl = 0.2,\
      trans = 0.2):
    '''The constructor for the rt_layers class.
    See the class documentation for details of inputs.
    '''
    self.Tol = Tol
    self.Iter = Iter
    self.K = K
    if int(N) % 2 == 1:
      N = int(N)+1
      print 'N rounded up to even number:', str(N)
    self.N = N
    self.Lc = Lc
    # choose between PROSPECT or refl trans input
    if np.isnan(refl) or np.isnan(trans):
      self.ln = ln
      self.cab = cab
      self.car = car
      self.cbrown = cbrown
      self.cw = cw
      self.cm = cm
      self.lamda = lamda
      refl, trans = prospect_py.prospect_5b(ln, cab, car, cbrown, cw,\
          cm)[lamda-401]
    else:
      self.ln = np.nan
      self.cab = np.nan
      self.car = np.nan
      self.cbrown = np.nan
      self.cw = np.nan
      self.cm = np.nan
      self.lamda = np.nan
    self.refl = refl
    self.trans = trans
    self.refl_s = refl_s
    self.Beta = Beta
    self.sun0_zen = sun0_zen * np.pi / 180.
    self.sun0_azi = sun0_azi * np.pi / 180.
    self.sun0 = np.array([self.sun0_zen, self.sun0_azi])
    self.mu_s = np.cos(self.sun0_zen)
    self.I0 = Beta * F / np.pi # did not include mu_s here which
    # which is part of original text. mu_s skews total. more 
    # likely to get proportion of sun at elevation.
    self.F = F
    # it is assumed that illumination at TOC will be provided prior.
    self.Id = (1. - Beta) * F / np.pi
    self.arch = arch
    self.albedo = self.refl + self.trans # leaf single scattering albedo
    f = open('quad_dict.dat')
    quad_dict = pickle.load(f)
    f.close()
    quad = quad_dict[str(N)]
    self.gauss_wt = quad[:,2] / 8.# per octant. 
    # see Lewis 1984 p.172 eq(4-40) 
    self.gauss_mu = np.cos(quad[:,0])
    self.views = np.array(zip(quad[:,0],quad[:,1]))

    # intervals
    dk = Lc/K
    self.mid_ks = np.arange(dk/2.,Lc,dk)
    self.n = N*(N + 2) # self.N/2 # needs to be mid of angle pairs
    
    # node arrays and boundary arrays
    self.views_zen = quad[:,0]
    self.views_azi = quad[:,1]
    self.sun_up = self.views[:self.n/2]
    self.sun_down = self.views[self.n/2:]
    self.Ird = -np.sum(np.multiply(self.refl_s * 2. * \
        np.multiply(self.gauss_mu[self.n/2:],\
        self.I_f(self.sun_down, self.Lc, self.Id)),\
        self.gauss_wt[self.n/2:]))
    self.Ir0 = self.refl_s * -self.mu_s * \
        self.I_f(self.sun0, self.Lc, self.I0)
    # discrete ordinate equations
    g = G(self.views_zen,self.arch)
    mu = self.gauss_mu 
    self.a = (1. + g*dk/2./mu)/(1. - g*dk/2./mu)
    self.b = (g*dk/mu)/(1. + g*dk/2./mu)
    self.c = (g*dk/mu)/(1. - g*dk/2./mu)
    # build in validation of N to counter negative fluxes.
    if any((g * dk / 2. / mu) > 1.):
      raise Exception('NegativeFluxPossible')
    # G-function cross-sections
    self.Gx = g
    self.Gs = G(self.sun0_zen,arch)
    self.Inodes = np.zeros((K,3,self.n)) # K, upper-mid-lower, N
    self.Jnodes = np.zeros((K,self.n))
    self.Q1nodes = self.Jnodes.copy()
    self.Q2nodes = self.Jnodes.copy()
    self.Q3nodes = self.Jnodes.copy()
    self.Q4nodes = self.Jnodes.copy()
    self.Px = np.zeros((self.n,self.n)) # P cross-section array
    self.Ps = np.zeros(self.n) # P array for solar zenith
    # a litte progress bar for long calcs
    widgets = ['Progress: ', Percentage(), ' ', \
      Bar(marker='0',left='[',right=']'), ' ', ETA()] 
    maxval = np.shape(self.views)[0] * (np.shape(self.mid_ks)[0] + \
        np.shape(self.views)[0] + 1) + 1
    pbar = ProgressBar(widgets=widgets, maxval = maxval)
    count = 0
    print 'Setting-up Phase and Q term arrays....'
    pbar.start()
    for (i,v) in enumerate(self.views):
      count += 1
      pbar.update(count)
      self.Ps[i] = P2(v,self.sun0,self.arch,self.refl,\
        self.trans)
    for (i,v1) in enumerate(self.views):
      for (j,v2) in enumerate(self.views):
        count += 1
        pbar.update(count)
        self.Px[i,j] = P2(v1, v2 ,self.arch, self.refl, self.trans)
    for (i, k) in enumerate(self.mid_ks):
      for (j, v) in enumerate(self.views):
        count += 1
        pbar.update(count)
        # the factors to the right were found through trial and 
        # error. They make calculations work....
        self.Q1nodes[i,j] = self.Q1(j,k)# * np.pi / 2. 
        self.Q2nodes[i,j] = self.Q2(j,k)# * np.pi / 2. * 3.
        self.Q3nodes[i,j] = self.Q3(j,k)# * np.pi / 2.
        self.Q4nodes[i,j] = self.Q4(j,k)# * np.pi / 2. * 3.
    pbar.finish()
    self.Bounds = np.zeros((2,self.n))
    os.system('play --no-show-progress --null --channels 1 \
            synth %s sine %f' % ( 0.5, 500)) # ring the bell
Beispiel #2
0
  def __init__(self, Tol = 1.e-2, Iter = 40, N = 6, lad_file=\
      'scene_out_turbid_big.dat', refl_s = 1.0, F = np.pi, Beta=1., \
      sun0_zen = 180., sun0_azi = 0., arch = 's', ln = 1.2, \
      cab = 30., car = 10., cbrown = 0., cw = 0.015, cm = 0.009, \
      lamda = 760, refl = 0.5, trans = 0.5, cont=True, perc=0.95):
    '''The constructor for the rt_layers class.
    See the class documentation for details of inputs.
    '''
    self.cont = cont
    self.perc = perc
    self.Tol = Tol
    self.Iter = Iter
    self.prev_perc = np.nan
    if int(N) % 2 == 1:
      N = int(N)+1
      print 'N rounded up to even number:', str(N)
    self.N = N
    # choose between PROSPECT or refl trans input
    if np.isnan(refl) or np.isnan(trans):
      self.ln = ln
      self.cab = cab
      self.car = car
      self.cbrown = cbrown
      self.cw = cw
      self.cm = cm
      self.lamda = lamda
      refl, trans = prospect_py.prospect_5b(ln, cab, car, cbrown, cw,\
          cm)[lamda-401]
    else:
      self.ln = np.nan
      self.cab = np.nan
      self.car = np.nan
      self.cbrown = np.nan
      self.cw = np.nan
      self.cm = np.nan
      self.lamda = np.nan
    self.refl = refl
    self.trans = trans
    self.refl_s = refl_s
    self.Beta = Beta
    self.sun0_zen = sun0_zen * np.pi / 180.
    self.sun0_azi = sun0_azi * np.pi / 180.
    self.sun0 = np.array([self.sun0_zen, self.sun0_azi])
    self.mu_s = np.cos(self.sun0_zen)
    self.I0 = Beta * F / np.pi # did not include mu_s here
    # which is part of original text. mu_s skews total. more 
    # likely to get proportion of sun at elevation.
    self.F = F
    # it is assumed that illumination at TOC will be provided prior.
    self.Id = (1. - Beta) * F / np.pi
    self.arch = arch
    self.albedo = self.refl + self.trans # leaf single scattering albedo
    f = open('quad_dict.dat')
    quad_dict = pickle.load(f)
    f.close()
    quad = quad_dict[str(N)]
    self.n = N*(N + 2) # total directions
    self.gauss_wt = quad[:,2] / 8.# * 8. / self.n * np.pi / 2.# per octant. 
    # see Lewis 1984 p.172 eq(4-40) and notes on 13/2/14 
    self.gauss_mu = np.cos(quad[:,0])
    self.gauss_eta = np.sqrt(1.-self.gauss_mu**2) * np.sin(quad[:,1])
    self.gauss_xi = np.sqrt(1.-self.gauss_mu**2) * np.cos(quad[:,1])
    self.views = np.array(zip(quad[:,0],quad[:,1]))

    # load LAD file
    self.lad_file = lad_file
    f = open(lad_file)
    dic = pickle.load(f)
    f.close()

    self.mesh = dic['mesh'] # coordinates of midpoints of cells in xyz

    # intervals
    self.dx = self.mesh[0,1] - self.mesh[0,0] # dk in 2 angle
    self.dy = self.mesh[1,1] - self.mesh[1,0]
    self.dz = self.mesh[2,1] - self.mesh[2,0]
    # grid of cell values in xyz divided by cell volume for lad
    self.grid = dic['grid'] / (self.dx * self.dy * self.dz)
    self.mid_xs = self.mesh[0] # mid_ks in 2 angle
    self.mid_ys = self.mesh[1]
    self.mid_zs = self.mesh[2]
    self.k = len(self.mid_xs)
    self.j = len(self.mid_ys)
    self.i = len(self.mid_zs)
    # directions grouped per octant
    self.octi = np.reshape(np.arange(0,self.n), (8,-1))
    # edges grouped per octant o from, t to. see notes 4/5/14
    self.edgo = np.array([[4,5,2],[0,5,2],[0,1,2],[4,1,2],[4,5,6],\
        [0,5,6],[0,1,6],[4,1,6]])
    self.edgt = np.array([[0,1,6],[4,1,6],[4,5,6],[0,5,6],[0,1,2],\
        [4,1,2],[4,5,2],[0,5,2]])
    # decision table on direction of flux transfer
    self.decide = np.array([[True,True,False],[False,True,False],\
        [False,False,False],[True,False,False],[True,True,True],\
        [False,True,True],[False,False,True],[True,False,True]])
    # end cube flux transfer octants and views. see notes 4/5/14
    self.xa = np.array([self.octi[it] for it in [0,3,4,7]]).flatten()
    self.xb = np.array([self.octi[it] for it in [1,2,5,6]]).flatten()
    self.ya = np.array([self.octi[it] for it in [0,1,4,5]]).flatten()
    self.yb = np.array([self.octi[it] for it in [2,3,6,7]]).flatten()
    # node arrays and boundary arrays
    self.views_zen = self.views[:,0]
    self.views_azi = self.views[:,1]
    # splits views into octants and sun_up and sun_down
    self.sun_down = self.views[self.n/2:]
    self.sun_up = self.views[:self.n/2]
    self.octv = np.reshape(self.views, (8, -1, 2)) # per octant views
    self.octw = np.reshape(self.gauss_wt, (8, -1)) # per octant wt
    # G-function cross-sections
    self.Gx = G(self.views_zen,self.arch) 
    self.Gs = G(self.sun0_zen,arch)
    # see notes on 29/04/14 for figure of Inode layout
    self.Inodes = np.zeros((self.k, self.j, self.i, 7, self.n)) 
    self.Jnodes = np.zeros((self.k, self.j, self.i, self.n))
    self.Q1nodes = self.Jnodes.copy()
    self.Q2nodes = self.Jnodes.copy()
    self.Q3nodes = self.Jnodes.copy()
    self.Q4nodes = self.Jnodes.copy()
    # use Gamma/pi as function and * by ul per cell to get cross sect
    self.Gampi_x = np.zeros((self.n,self.n)) # part cross-section array
    self.Gampi_s = np.zeros(self.n) # part of array for solar zenith
    self.Ps = self.Gampi_s.copy() # to test P theory
    # a litte progress bar for long calcs
    widgets = ['Progress: ', Percentage(), ' ', \
      Bar(marker='0',left='[',right=']'), ' ', ETA()] 
    maxval = np.shape(self.views)[0] * (1 + np.shape(self.views)[0] +\
        self.i*self.j*self.k) + 1
    pbar = ProgressBar(widgets=widgets, maxval = maxval)
    count = 0
    print 'Setting-up Phase and Q term arrays....'
    pbar.start()
    for (i,v) in enumerate(self.views):
      count += 1
      pbar.update(count)
      self.Gampi_s[i] = Gamma2(v,self.sun0,self.arch,self.refl,\
        self.trans) / np.pi # sun view part
      #self.Ps[i] = P2(v, self.sun0, self.arch, self.refl, self.trans)
    for (i,v1) in enumerate(self.views):
      for (j,v2) in enumerate(self.views):
        count += 1
        pbar.update(count)
        self.Gampi_x[i,j] = Gamma2(v1, v2 ,self.arch, self.refl,\
            self.trans) / np.pi # all other views parts
    self.tot_lai_grid = np.sum(self.grid, 2)
    for k in np.arange(0,self.k): # x axis
      for j in np.arange(0,self.j): # y axis
        tot_lai = self.tot_lai_grid[k,j]
        lai = self.grid[k,j]
        cum_lai = np.insert(np.cumsum(self.grid[k,j]), 0, 0.)
        # soil flux needs to be calculated per bottom cell
        Ird = self.refl_s / np.pi * np.sum(np.multiply(\
            np.multiply(-self.gauss_mu[self.n/2:],\
            self.I_f(self.sun_down, tot_lai, self.Id)),\
            self.gauss_wt[self.n/2:])) # diffuse part
        Ir0 = self.refl_s * -self.mu_s / np.pi * \
            self.I_f(self.sun0, tot_lai, self.I0) # direct part
        for i, z in enumerate(self.mid_zs): # z axis
          # test for zero lai pockets, keep scattering at zero
          if np.allclose(0.,lai[i], rtol=1e-08, atol=1e-08):
            count += 1*self.n
            print 'zero lai encountered at cell: (%d, %d, %d)' %(k,j,i)
            pbar.update(count)
            continue
          mid_lai = lai[i]/2. + cum_lai[i]
          pnt_lai = lai[i]
          for l, v in enumerate(self.views):
            count += 1
            pbar.update(count)
            self.Q1nodes[k,j,i,l] = self.Q1(l,pnt_lai,mid_lai)\
                * np.pi/2. * np.pi * 4. / 3. 
            self.Q2nodes[k,j,i,l] = self.Q2(l,pnt_lai,mid_lai)\
                * np.pi/2. * 3.
            self.Q3nodes[k,j,i,l] = self.Q3(l,pnt_lai,mid_lai,\
                tot_lai, Ir0) * np.pi/2.
            self.Q4nodes[k,j,i,l] = self.Q4(l,pnt_lai,mid_lai,\
                tot_lai, Ird) * np.pi/2. * 3.
    pbar.finish()
    self.PrevInodes = self.Inodes.copy()
    os.system('play --no-show-progress --null --channels 1 \
            synth %s sine %f' % ( 0.5, 500)) # ring the bell
Beispiel #3
0
    def __init__(self, Tol = 1.e-2, Iter = 40, N = 6, lad_file=\
        'scene_out_turbid_big.dat', refl_s = 1.0, F = np.pi, Beta=1., \
        sun0_zen = 180., sun0_azi = 0., arch = 's', ln = 1.2, \
        cab = 30., car = 10., cbrown = 0., cw = 0.015, cm = 0.009, \
        lamda = 760, refl = 0.5, trans = 0.5, cont=True, perc=0.95):
        '''The constructor for the rt_layers class.
    See the class documentation for details of inputs.
    '''
        self.cont = cont
        self.perc = perc
        self.Tol = Tol
        self.Iter = Iter
        self.prev_perc = np.nan
        if int(N) % 2 == 1:
            N = int(N) + 1
            print 'N rounded up to even number:', str(N)
        self.N = N
        # choose between PROSPECT or refl trans input
        if np.isnan(refl) or np.isnan(trans):
            self.ln = ln
            self.cab = cab
            self.car = car
            self.cbrown = cbrown
            self.cw = cw
            self.cm = cm
            self.lamda = lamda
            refl, trans = prospect_py.prospect_5b(ln, cab, car, cbrown, cw,\
                cm)[lamda-401]
        else:
            self.ln = np.nan
            self.cab = np.nan
            self.car = np.nan
            self.cbrown = np.nan
            self.cw = np.nan
            self.cm = np.nan
            self.lamda = np.nan
        self.refl = refl
        self.trans = trans
        self.refl_s = refl_s
        self.Beta = Beta
        self.sun0_zen = sun0_zen * np.pi / 180.
        self.sun0_azi = sun0_azi * np.pi / 180.
        self.sun0 = np.array([self.sun0_zen, self.sun0_azi])
        self.mu_s = np.cos(self.sun0_zen)
        self.I0 = Beta * F / np.pi  # did not include mu_s here
        # which is part of original text. mu_s skews total. more
        # likely to get proportion of sun at elevation.
        self.F = F
        # it is assumed that illumination at TOC will be provided prior.
        self.Id = (1. - Beta) * F / np.pi
        self.arch = arch
        self.albedo = self.refl + self.trans  # leaf single scattering albedo
        f = open('quad_dict.dat')
        quad_dict = pickle.load(f)
        f.close()
        quad = quad_dict[str(N)]
        self.n = N * (N + 2)  # total directions
        self.gauss_wt = quad[:,
                             2] / 8.  # * 8. / self.n * np.pi / 2.# per octant.
        # see Lewis 1984 p.172 eq(4-40) and notes on 13/2/14
        self.gauss_mu = np.cos(quad[:, 0])
        self.gauss_eta = np.sqrt(1. - self.gauss_mu**2) * np.sin(quad[:, 1])
        self.gauss_xi = np.sqrt(1. - self.gauss_mu**2) * np.cos(quad[:, 1])
        self.views = np.array(zip(quad[:, 0], quad[:, 1]))

        # load LAD file
        self.lad_file = lad_file
        f = open(lad_file)
        dic = pickle.load(f)
        f.close()

        self.mesh = dic['mesh']  # coordinates of midpoints of cells in xyz

        # intervals
        self.dx = self.mesh[0, 1] - self.mesh[0, 0]  # dk in 2 angle
        self.dy = self.mesh[1, 1] - self.mesh[1, 0]
        self.dz = self.mesh[2, 1] - self.mesh[2, 0]
        # grid of cell values in xyz divided by cell volume for lad
        self.grid = dic['grid'] / (self.dx * self.dy * self.dz)
        self.mid_xs = self.mesh[0]  # mid_ks in 2 angle
        self.mid_ys = self.mesh[1]
        self.mid_zs = self.mesh[2]
        self.k = len(self.mid_xs)
        self.j = len(self.mid_ys)
        self.i = len(self.mid_zs)
        # directions grouped per octant
        self.octi = np.reshape(np.arange(0, self.n), (8, -1))
        # edges grouped per octant o from, t to. see notes 4/5/14
        self.edgo = np.array([[4,5,2],[0,5,2],[0,1,2],[4,1,2],[4,5,6],\
            [0,5,6],[0,1,6],[4,1,6]])
        self.edgt = np.array([[0,1,6],[4,1,6],[4,5,6],[0,5,6],[0,1,2],\
            [4,1,2],[4,5,2],[0,5,2]])
        # decision table on direction of flux transfer
        self.decide = np.array([[True,True,False],[False,True,False],\
            [False,False,False],[True,False,False],[True,True,True],\
            [False,True,True],[False,False,True],[True,False,True]])
        # end cube flux transfer octants and views. see notes 4/5/14
        self.xa = np.array([self.octi[it] for it in [0, 3, 4, 7]]).flatten()
        self.xb = np.array([self.octi[it] for it in [1, 2, 5, 6]]).flatten()
        self.ya = np.array([self.octi[it] for it in [0, 1, 4, 5]]).flatten()
        self.yb = np.array([self.octi[it] for it in [2, 3, 6, 7]]).flatten()
        # node arrays and boundary arrays
        self.views_zen = self.views[:, 0]
        self.views_azi = self.views[:, 1]
        # splits views into octants and sun_up and sun_down
        self.sun_down = self.views[self.n / 2:]
        self.sun_up = self.views[:self.n / 2]
        self.octv = np.reshape(self.views, (8, -1, 2))  # per octant views
        self.octw = np.reshape(self.gauss_wt, (8, -1))  # per octant wt
        # G-function cross-sections
        self.Gx = G(self.views_zen, self.arch)
        self.Gs = G(self.sun0_zen, arch)
        # see notes on 29/04/14 for figure of Inode layout
        self.Inodes = np.zeros((self.k, self.j, self.i, 7, self.n))
        self.Jnodes = np.zeros((self.k, self.j, self.i, self.n))
        self.Q1nodes = self.Jnodes.copy()
        self.Q2nodes = self.Jnodes.copy()
        self.Q3nodes = self.Jnodes.copy()
        self.Q4nodes = self.Jnodes.copy()
        # use Gamma/pi as function and * by ul per cell to get cross sect
        self.Gampi_x = np.zeros((self.n, self.n))  # part cross-section array
        self.Gampi_s = np.zeros(self.n)  # part of array for solar zenith
        self.Ps = self.Gampi_s.copy()  # to test P theory
        # a litte progress bar for long calcs
        widgets = ['Progress: ', Percentage(), ' ', \
          Bar(marker='0',left='[',right=']'), ' ', ETA()]
        maxval = np.shape(self.views)[0] * (1 + np.shape(self.views)[0] +\
            self.i*self.j*self.k) + 1
        pbar = ProgressBar(widgets=widgets, maxval=maxval)
        count = 0
        print 'Setting-up Phase and Q term arrays....'
        pbar.start()
        for (i, v) in enumerate(self.views):
            count += 1
            pbar.update(count)
            self.Gampi_s[i] = Gamma2(v,self.sun0,self.arch,self.refl,\
              self.trans) / np.pi # sun view part
            #self.Ps[i] = P2(v, self.sun0, self.arch, self.refl, self.trans)
        for (i, v1) in enumerate(self.views):
            for (j, v2) in enumerate(self.views):
                count += 1
                pbar.update(count)
                self.Gampi_x[i,j] = Gamma2(v1, v2 ,self.arch, self.refl,\
                    self.trans) / np.pi # all other views parts
        self.tot_lai_grid = np.sum(self.grid, 2)
        for k in np.arange(0, self.k):  # x axis
            for j in np.arange(0, self.j):  # y axis
                tot_lai = self.tot_lai_grid[k, j]
                lai = self.grid[k, j]
                cum_lai = np.insert(np.cumsum(self.grid[k, j]), 0, 0.)
                # soil flux needs to be calculated per bottom cell
                Ird = self.refl_s / np.pi * np.sum(np.multiply(\
                    np.multiply(-self.gauss_mu[self.n/2:],\
                    self.I_f(self.sun_down, tot_lai, self.Id)),\
                    self.gauss_wt[self.n/2:])) # diffuse part
                Ir0 = self.refl_s * -self.mu_s / np.pi * \
                    self.I_f(self.sun0, tot_lai, self.I0) # direct part
                for i, z in enumerate(self.mid_zs):  # z axis
                    # test for zero lai pockets, keep scattering at zero
                    if np.allclose(0., lai[i], rtol=1e-08, atol=1e-08):
                        count += 1 * self.n
                        print 'zero lai encountered at cell: (%d, %d, %d)' % (
                            k, j, i)
                        pbar.update(count)
                        continue
                    mid_lai = lai[i] / 2. + cum_lai[i]
                    pnt_lai = lai[i]
                    for l, v in enumerate(self.views):
                        count += 1
                        pbar.update(count)
                        self.Q1nodes[k,j,i,l] = self.Q1(l,pnt_lai,mid_lai)\
                            * np.pi/2. * np.pi * 4. / 3.
                        self.Q2nodes[k,j,i,l] = self.Q2(l,pnt_lai,mid_lai)\
                            * np.pi/2. * 3.
                        self.Q3nodes[k,j,i,l] = self.Q3(l,pnt_lai,mid_lai,\
                            tot_lai, Ir0) * np.pi/2.
                        self.Q4nodes[k,j,i,l] = self.Q4(l,pnt_lai,mid_lai,\
                            tot_lai, Ird) * np.pi/2. * 3.
        pbar.finish()
        self.PrevInodes = self.Inodes.copy()
        os.system('play --no-show-progress --null --channels 1 \
            synth %s sine %f' % (0.5, 500))  # ring the bell
Beispiel #4
0
    def __init__(self, Tol = 1.e-6, Iter = 200, K = 10, N = 6,\
        Lc = 2.0, refl_s = 0.0, F = np.pi, Beta=.0, sun0_zen = 180.,\
        sun0_azi = 0.0, arch = 'u', ln = 1.2, cab = 30., car = 10., \
        cbrown = 0., cw = 0.015, cm = 0.009, lamda = 760, refl = 0.2,\
        trans = 0.2):
        '''The constructor for the rt_layers class.
    See the class documentation for details of inputs.
    '''
        self.Tol = Tol
        self.Iter = Iter
        self.K = K
        if int(N) % 2 == 1:
            N = int(N) + 1
            print 'N rounded up to even number:', str(N)
        self.N = N
        self.Lc = Lc
        # choose between PROSPECT or refl trans input
        if np.isnan(refl) or np.isnan(trans):
            self.ln = ln
            self.cab = cab
            self.car = car
            self.cbrown = cbrown
            self.cw = cw
            self.cm = cm
            self.lamda = lamda
            refl, trans = prospect_py.prospect_5b(ln, cab, car, cbrown, cw,\
                cm)[lamda-401]
        else:
            self.ln = np.nan
            self.cab = np.nan
            self.car = np.nan
            self.cbrown = np.nan
            self.cw = np.nan
            self.cm = np.nan
            self.lamda = np.nan
        self.refl = refl
        self.trans = trans
        self.refl_s = refl_s
        self.Beta = Beta
        self.sun0_zen = sun0_zen * np.pi / 180.
        self.sun0_azi = sun0_azi * np.pi / 180.
        self.sun0 = np.array([self.sun0_zen, self.sun0_azi])
        self.mu_s = np.cos(self.sun0_zen)
        self.I0 = Beta * F / np.pi  # did not include mu_s here which
        # which is part of original text. mu_s skews total. more
        # likely to get proportion of sun at elevation.
        self.F = F
        # it is assumed that illumination at TOC will be provided prior.
        self.Id = (1. - Beta) * F / np.pi
        self.arch = arch
        self.albedo = self.refl + self.trans  # leaf single scattering albedo
        f = open('quad_dict.dat')
        quad_dict = pickle.load(f)
        f.close()
        quad = quad_dict[str(N)]
        self.gauss_wt = quad[:, 2] / 8.  # per octant.
        # see Lewis 1984 p.172 eq(4-40)
        self.gauss_mu = np.cos(quad[:, 0])
        self.views = np.array(zip(quad[:, 0], quad[:, 1]))

        # intervals
        dk = Lc / K
        self.mid_ks = np.arange(dk / 2., Lc, dk)
        self.n = N * (N + 2)  # self.N/2 # needs to be mid of angle pairs

        # node arrays and boundary arrays
        self.views_zen = quad[:, 0]
        self.views_azi = quad[:, 1]
        self.sun_up = self.views[:self.n / 2]
        self.sun_down = self.views[self.n / 2:]
        self.Ird = -np.sum(np.multiply(self.refl_s * 2. * \
            np.multiply(self.gauss_mu[self.n/2:],\
            self.I_f(self.sun_down, self.Lc, self.Id)),\
            self.gauss_wt[self.n/2:]))
        self.Ir0 = self.refl_s * -self.mu_s * \
            self.I_f(self.sun0, self.Lc, self.I0)
        # discrete ordinate equations
        g = G(self.views_zen, self.arch)
        mu = self.gauss_mu
        self.a = (1. + g * dk / 2. / mu) / (1. - g * dk / 2. / mu)
        self.b = (g * dk / mu) / (1. + g * dk / 2. / mu)
        self.c = (g * dk / mu) / (1. - g * dk / 2. / mu)
        # build in validation of N to counter negative fluxes.
        if any((g * dk / 2. / mu) > 1.):
            raise Exception('NegativeFluxPossible')
        # G-function cross-sections
        self.Gx = g
        self.Gs = G(self.sun0_zen, arch)
        self.Inodes = np.zeros((K, 3, self.n))  # K, upper-mid-lower, N
        self.Jnodes = np.zeros((K, self.n))
        self.Q1nodes = self.Jnodes.copy()
        self.Q2nodes = self.Jnodes.copy()
        self.Q3nodes = self.Jnodes.copy()
        self.Q4nodes = self.Jnodes.copy()
        self.Px = np.zeros((self.n, self.n))  # P cross-section array
        self.Ps = np.zeros(self.n)  # P array for solar zenith
        # a litte progress bar for long calcs
        widgets = ['Progress: ', Percentage(), ' ', \
          Bar(marker='0',left='[',right=']'), ' ', ETA()]
        maxval = np.shape(self.views)[0] * (np.shape(self.mid_ks)[0] + \
            np.shape(self.views)[0] + 1) + 1
        pbar = ProgressBar(widgets=widgets, maxval=maxval)
        count = 0
        print 'Setting-up Phase and Q term arrays....'
        pbar.start()
        for (i, v) in enumerate(self.views):
            count += 1
            pbar.update(count)
            self.Ps[i] = P2(v,self.sun0,self.arch,self.refl,\
              self.trans)
        for (i, v1) in enumerate(self.views):
            for (j, v2) in enumerate(self.views):
                count += 1
                pbar.update(count)
                self.Px[i, j] = P2(v1, v2, self.arch, self.refl, self.trans)
        for (i, k) in enumerate(self.mid_ks):
            for (j, v) in enumerate(self.views):
                count += 1
                pbar.update(count)
                # the factors to the right were found through trial and
                # error. They make calculations work....
                self.Q1nodes[i, j] = self.Q1(j, k)  # * np.pi / 2.
                self.Q2nodes[i, j] = self.Q2(j, k)  # * np.pi / 2. * 3.
                self.Q3nodes[i, j] = self.Q3(j, k)  # * np.pi / 2.
                self.Q4nodes[i, j] = self.Q4(j, k)  # * np.pi / 2. * 3.
        pbar.finish()
        self.Bounds = np.zeros((2, self.n))
        os.system('play --no-show-progress --null --channels 1 \
            synth %s sine %f' % (0.5, 500))  # ring the bell