<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def FlowAccumulation( dem, method = None, exponent = None, weights = None, in_place = False ):
 """Calculates flow accumulation. A variety of methods are available. Args: dem (rdarray):
 An elevation model method (str):
 Flow accumulation method to use. (See below.) exponent (float):
 Some methods require an exponent; refer to the relevant publications for details. weights (rdarray):
 Flow accumulation weights to use. This is the amount of flow generated by each cell. If this is not provided, each cell will generate 1 unit of flow. in_place (bool):
 If True, then `weights` is modified in place. An accumulation matrix is always returned, but it will just be a view of the modified data if `in_place` is True. =================== ============================== =========================== Method Note Reference =================== ============================== =========================== Tarboton Alias for Dinf. `Taroboton (1997) doi: 10.1029/96WR03137 <http://dx.doi.org/10.1029/96WR03137>`_ Dinf Alias for Tarboton. `Taroboton (1997) doi: 10.1029/96WR03137 <http://dx.doi.org/10.1029/96WR03137>`_ Quinn Holmgren with exponent=1. `Quinn et al. (1991) doi: 10.1002/hyp.3360050106 <http://dx.doi.org/10.1002/hyp.3360050106>`_ Holmgren(E) Generalization of Quinn. `Holmgren (1994) doi: 10.1002/hyp.3360080405 <http://dx.doi.org/10.1002/hyp.3360080405>`_ Freeman(E) TODO `Freeman (1991) doi: 10.1016/0098-3004(91)90048-I <http://dx.doi.org/10.1016/0098-3004(91)90048-I>`_ FairfieldLeymarieD8 Alias for Rho8. `Fairfield and Leymarie (1991) doi: 10.1029/90WR02658 <http://dx.doi.org/10.1029/90WR02658>`_ FairfieldLeymarieD4 Alias for Rho4. `Fairfield and Leymarie (1991) doi: 10.1029/90WR02658 <http://dx.doi.org/10.1029/90WR02658>`_ Rho8 Alias for FairfieldLeymarieD8. `Fairfield and Leymarie (1991) doi: 10.1029/90WR02658 <http://dx.doi.org/10.1029/90WR02658>`_ Rho4 Alias for FairfieldLeymarieD4. `Fairfield and Leymarie (1991) doi: 10.1029/90WR02658 <http://dx.doi.org/10.1029/90WR02658>`_ OCallaghanD8 Alias for D8. `O'Callaghan and Mark (1984) doi: 10.1016/S0734-189X(84)80011-0 <http://dx.doi.org/10.1016/S0734-189X(84)80011-0>`_ OCallaghanD4 Alias for D8. `O'Callaghan and Mark (1984) doi: 10.1016/S0734-189X(84)80011-0 <http://dx.doi.org/10.1016/S0734-189X(84)80011-0>`_ D8 Alias for OCallaghanD8. `O'Callaghan and Mark (1984) doi: 10.1016/S0734-189X(84)80011-0 <http://dx.doi.org/10.1016/S0734-189X(84)80011-0>`_ D4 Alias for OCallaghanD4. `O'Callaghan and Mark (1984) doi: 10.1016/S0734-189X(84)80011-0 <http://dx.doi.org/10.1016/S0734-189X(84)80011-0>`_ =================== ============================== =========================== **Methods marked (E) require the exponent argument.** Returns: A flow accumulation according to the desired method. If `weights` was provided and `in_place` was True, then this matrix is a view of the modified data. """

  if type(dem) is not rdarray:
    raise Exception("A richdem.rdarray or numpy.ndarray is required!")

  facc_methods = {
    "Tarboton":            _richdem.FA_Tarboton,
    "Dinf":                _richdem.FA_Tarboton,
    "Quinn":               _richdem.FA_Quinn,
    "FairfieldLeymarieD8": _richdem.FA_FairfieldLeymarieD8,
    "FairfieldLeymarieD4": _richdem.FA_FairfieldLeymarieD4,
    "Rho8":                _richdem.FA_Rho8,
    "Rho4":                _richdem.FA_Rho4,
    "OCallaghanD8":        _richdem.FA_OCallaghanD8,
    "OCallaghanD4":        _richdem.FA_OCallaghanD4,
    "D8":                  _richdem.FA_D8,
    "D4":                  _richdem.FA_D4
  }

  facc_methods_exponent = {
    "Freeman":           _richdem.FA_Freeman,
    "Holmgren":          _richdem.FA_Holmgren
  }

  if   weights is not None and     in_place:
    accum = rdarray(weights, no_data=-1)
  elif weights is not None and not in_place:
    accum = rdarray(weights, copy=True, meta_obj=dem, no_data=-1)
  elif weights is None:
    accum = rdarray(np.ones(shape=dem.shape, dtype='float64'), meta_obj=dem, no_data=-1)
  else:
    raise Exception("Execution should never reach this point!")

  if accum.dtype!='float64':
    raise Exception("Accumulation array must be of type 'float64'!")

  accumw = accum.wrap()

  _AddAnalysis(accum, "FlowAccumulation(dem, method={method}, exponent={exponent}, weights={weights}, in_place={in_place})".format(
    method   = method,
    exponent = exponent,
    weights  = 'None' if weights is None else 'weights',
    in_place = in_place
  ))

  if method in facc_methods:
    facc_methods[method](dem.wrap(),accumw)
  elif method in facc_methods_exponent:
    if exponent is None:
      raise Exception('FlowAccumulation method "'+method+'" requires an exponent!')
    facc_methods_exponent[method](dem.wrap(),accumw,exponent)
  else:
    raise Exception("Invalid FlowAccumulation method. Valid methods are: " + ', '.join(list(facc_methods.keys()) + list(facc_methods_exponent.keys()) ))

  accum.copyFromWrapped(accumw)

  return accum