Ejemplo n.º 1
0
def DEM_creator(H, H_wt, seed, elev_range, max_level, gradient_values, DEMcreator_option):
    """
    Generates a DEM map with specified parameters described below.
    Args:
        H    : List containing H values         --> [H1, H2, H3, ...]( List of floats )
        H_wt : List containing H_wt             --> [H1_wt, H2_wt, H3_wt, ...] ( List of floats )
        seed : seed for random no generator     --> [seed1, seed2 seed3, ...] ( list of ints)
        elev_range: List containing elev bounds --> [elev_min, elev_max] (int, int) 
        max_level : size if grid 2^(max_level) + 1   ( int )
        gradient_values: list containing gradient values (List of float values)
        DEMcreator_option: Specify the method used to generate DEM (fm2D or SS)       
    Result:
        Output : [ DEM_arr, [List of DEM input grids], [ List of DEM input grid names ], [list of parameters for DEM input grid]]
               where DEM_arr :Final Output DEM grid  
    """
    Input_DEMs = []
    name = []
    parameter = []
    if DEMcreator_option == 'fm2D':
        #Generate first DEM with gradient = 1 (i.e. TRUE) using FM2D method
        DEM_arr = MapGeneration_pure_python.midPointFm2d(max_level = max_level, sigma = 1, H = H[0], addition = True,\
                                          wrap = False, gradient = 1, seed = seed[0], normalise=True, bounds = elev_range, gradient_values = gradient_values)
        Input_DEMs.append(DEM_arr)
        file_name = "InputDEM_arr%d" % (1)
        name.append(file_name)
        parameter.append((H[0], H_wt[0]))
        DEM_arr = DEM_arr*H_wt[0]        
        for i in range(1,len(H)):    
            #Generate other DEM's with gradient = 0 (i.e. FLASE) and method specified by DEMcreator_option         
            temp_arr = MapGeneration_pure_python.midPointFm2d(max_level = max_level, sigma = 1, H = H[i], addition = True,\
                                         wrap = False, gradient = 0, seed = seed[i], normalise = True, bounds = elev_range, gradient_values = gradient_values)
            Input_DEMs.append(temp_arr)
            file_name = "InputDEM_arr%d" % (i+1)
            name.append(file_name)
            parameter.append((H[i], H_wt[i]))
            DEM_arr = DEM_arr +  H_wt[i]*temp_arr     
    else:
        #Generate first DEM with gradient = 1 (i.e. TRUE) using FM2D method
        DEM_arr = MapGeneration_pure_python.midPointFm2d(max_level = max_level, sigma = 1, H = H[0], addition = True,\
                                          wrap = False, gradient = 1, seed = seed[0], normalise=True, bounds = elev_range, gradient_values = gradient_values)
        DEM_arr = DEM_arr[:-1,:-1] # omit last row and last col to maintain consistency with Spectral method output grid 
        Input_DEMs.append(DEM_arr)
        file_name = "InputDEM_arr%d" % (1)
        name.append(file_name)
        parameter.append((H[0], H_wt[0]))
        DEM_arr = H_wt[0]*DEM_arr

        for i in range(1,len(H)):
            #Generate other DEM's with gradient = 0 (i.e. FLASE) and method specified by DEMcreator_option i.e SS in this case    
            temp_arr = SpectralSynthesisFM2D.SpectralSynthesisFM2D(max_level = max_level, sigma = 1, H = H[i],\
                                                   seed = seed[i], normalise = True, bounds = elev_range)
            Input_DEMs.append(temp_arr)
            file_name = "InputDEM_arr%d" % (i+1)
            name.append(file_name)
            parameter.append((H[i], H_wt[i]))
            DEM_arr = DEM_arr +  H_wt[i]*temp_arr

    Output = [DEM_arr, Input_DEMs, name, parameter] 
    return Output
def RiverNetwork(H1, H1wt, H2, H2wt, H3, H3wt, elev_min, elev_max):

  print "Generating Digital Elevation Maps using FM2D algorithm"

  #Generate first DEM with gradient = 1 (i.e. TRUE) and high H value 
  DEM_arr1 = MapGeneration_pure_python.midPointFm2d(max_level = 9, sigma = 1, H = H1, addition = True,\
                        wrap = False, gradient = 1,seed = 0, normalise=True,lbound=elev_min, ubound=elev_max)
  pylab.imsave("Output/DigitalElevationModel1",DEM_arr1)

  #Generate second DEM with gradient = 0 (i.e. FLASE) and medium H value 
  DEM_arr2 = MapGeneration_pure_python.midPointFm2d(max_level = 9, sigma = 1, H = H2, addition = True,\
                        wrap = False, gradient = 0,seed = 65, normalise = True,lbound=elev_min, ubound=elev_max)
  pylab.imsave("Output/DigitalElevationModel2",DEM_arr2)

  #Generate third DEM with gradient = 0 (i.e. FLASE) and medium H value 
  DEM_arr3 = MapGeneration_pure_python.midPointFm2d(max_level = 9, sigma = 1, H = H3, addition = True,\
                        wrap = False, gradient = 0,seed = 6, normalise = True,lbound=elev_min, ubound=elev_max)
  pylab.imsave("Output/DigitalElevationModel3",DEM_arr3)

  DEM_arr = DEM_arr1
  (x_len,y_len) = DEM_arr.shape
  #Get the co-ordinates having highest elev , required for catchment extraction
  (max_x, max_y) = ndimage.maximum_position(DEM_arr)

  for i in range(0,x_len):
    for j in range(0,y_len):
      #Combine 3 DEM's 
      DEM_arr[i][j] = (H1wt * DEM_arr1[i][j]) + (H2wt * DEM_arr2[i][j]) + (H3wt * DEM_arr3[i][j])
      

  print "Iteratively removing sink using 3x3 window"
  for p in range(0,6):
    for i in range(1,x_len-1):
      for j in range(1,y_len-1):
        #Remove pits by 3 x 3 window
        A = min(DEM_arr[i-1][j-1],DEM_arr[i-1][j],DEM_arr[i-1][j+1],\
                DEM_arr[i][j-1],DEM_arr[i][j+1],DEM_arr[i+1][j-1],
                DEM_arr[i+1][j],DEM_arr[i+1][j+1])
        if DEM_arr[i][j] < A:
          DEM_arr[i][j] = A + 1

  #Initialize various arrays to hold flow direction, Flow accumulation,catchment info etc
  Flow_arr = numpy.zeros((x_len,y_len) , dtype = "uint8" )
  # River_arr will hold the River_accumulation matrix
  River_arr = numpy.ones((x_len,y_len) , dtype = "int" )
  # Catchment_boundary_arr will hold the Catchment boundaries
  Catchment_boundary_arr = numpy.zeros((x_len,y_len) , dtype = "uint8" )
  # Found_arr will hold the catchment with different labels
  Found_arr = numpy.zeros((x_len,y_len),dtype = "uint8")
  # Pour_point_arr keeps track of pour point of a catchment on the map
  Pour_point_arr = numpy.zeros((x_len,y_len),dtype = "uint8")
  Pour_point_list = [] #keep track of Pour_point in a list

  pit_list = [] #contains all the pit in DEM
  print "Assigning Flow Directions"
  for i in range(1,x_len-1): 
    for j in range(1,y_len-1):
      #Assign Flow direction
      (value,dirn) =max(((DEM_arr[i][j] - DEM_arr[i-1][j-1])/1.41,3),\
                    (DEM_arr[i][j]-DEM_arr[i-1][j],2),((DEM_arr[i][j]-DEM_arr[i-1][j+1])/1.41,1),\
                    (DEM_arr[i][j] - DEM_arr[i][j-1],4),(0,8),(DEM_arr[i][j] - DEM_arr[i][j+1],0),\
                    ((DEM_arr[i][j] - DEM_arr[i+1][j-1])/1.41,5),(DEM_arr[i][j] - DEM_arr[i+1][j],6),\
                    ((DEM_arr[i][j] - DEM_arr[i+1][j+1])/1.41,7))
      Flow_arr[i][j] = dirn
      if dirn == 8:
        # If there is a pit append it to the pit_list
        pit_list.append((i,j))

  label = 0 # will be used to assign labels to differnet catchments

#_____________Catchment Extraction_____________________________________________
  print "Extracting Catchment and filling Depressions"
  while len(pit_list) >= 1:
  #_______________For each and every pit in the DEM do _________________________
    stack = []
    pit = pit_list.pop(0)
    stack.append(pit)
    label = label + 1 #increase the label being assigned to the catchment 
    #_______________________Identify catchment for each and every pit
    catchment_pixels = []
    catchment_pixels.append((DEM_arr[pit[0],pit[1]],pit[0],pit[1]))
    while len(stack) > 0:
      (p,q) = stack.pop(0)
      Found_arr[p][q] = label
      #Pop an element from stack check if its adjacent pixels exist and contribute 
      # its flow to the central pixel(pixel popped) then append it into list, continue
      # this while stack gets empty
      if pixel_exist(p-1,q-1,x_len,y_len):
        if Flow_arr[p-1][q-1] == 7:
          stack.append((p-1,q-1))
          catchment_pixels.append((DEM_arr[p-1,q-1],p-1,q-1))
      if pixel_exist(p-1,q,x_len,y_len):
        if Flow_arr[p-1][q] == 6 :
          catchment_pixels.append((DEM_arr[p-1,q],p-1,q))
          stack.append((p-1,q))
      if pixel_exist(p-1,q+1,x_len,y_len):
        if Flow_arr[p-1][q+1] == 5:
          catchment_pixels.append((DEM_arr[p-1,q+1],p-1,q+1))
          stack.append((p-1,q+1))
      if pixel_exist(p,q-1,x_len,y_len):
        if Flow_arr[p][q-1] == 0 :
          catchment_pixels.append((DEM_arr[p,q-1],p,q-1))
          stack.append((p,q-1))
      if pixel_exist(p,q+1,x_len,y_len):
        if Flow_arr[p][q+1] == 4:
          catchment_pixels.append((DEM_arr[p,q+1],p,q+1))
          stack.append((p,q+1))
      if pixel_exist(p+1,q-1,x_len,y_len):
        if Flow_arr[p+1][q-1] == 1:
          catchment_pixels.append((DEM_arr[p+1,q-1],p+1,q-1))
          stack.append((p+1,q-1))
      if pixel_exist(p+1,q,x_len,y_len):
        if Flow_arr[p+1][q] == 2 :
          catchment_pixels.append((DEM_arr[p+1,q],p+1,q))
          stack.append((p+1,q))
      if pixel_exist(p+1,q+1,x_len,y_len):
        if Flow_arr[p+1][q+1] == 3 :
          catchment_pixels.append((DEM_arr[p+1,q+1],p+1,q+1))
          stack.append((p+1,q+1))
    # Find catchment Outlet
    pour_point = (max_x, max_y)
    flag = 0
    for i in range(0,len(catchment_pixels)):
      (p,q) = ( catchment_pixels[i][1],catchment_pixels[i][2] )
      label = Found_arr[p][q]
      # Catchment Outlet will be the minimum catchment boundary pixel
      if (Found_arr[p-1][q-1] != label or Found_arr[p-1][q] != label or Found_arr[p-1][q+1] != label or 
         Found_arr[p][q-1] != label or Found_arr[p][q+1] != label or Found_arr[p+1][q-1] != label or
         Found_arr[p+1][q] != label or Found_arr[p+1][q+1] != label):# if pixel lie on boundary of catchment
        Catchment_boundary_arr[p][q] = 255
        if DEM_arr[ pour_point[0] ][ pour_point[1] ] > DEM_arr[p][q]:#if height of boundary is less then update pour point
          pour_point = (p,q)
          flag = 1
    if flag == 1:
      Pour_point_list.append((DEM_arr[pour_point],pour_point[0],pour_point[1]))
      Pour_point_arr[pour_point] = 255
      for i in range(0,len(catchment_pixels)):
        if catchment_pixels[i][0] < DEM_arr[pour_point]:
          #fill the depression in the catchment
          DEM_arr[catchment_pixels[i][1],catchment_pixels[i][2]] = DEM_arr[pour_point]

  print "Assignnig flow dirnection again after Depression filling"
  for i in range(1,x_len-1):
    for j in range(1,y_len-1):
    # Again assign Flow direction again after filling the depressions
      (value, dirn ) = max( ((DEM_arr[i][j] - DEM_arr[i-1][j-1])/1.41,3),(DEM_arr[i][j] - DEM_arr[i-1][j],2),((DEM_arr[i][j] - DEM_arr[i-1][j+1])/1.41,1),\
                            (DEM_arr[i][j] - DEM_arr[i][j-1],4),(0,8),(DEM_arr[i][j] - DEM_arr[i][j+1],0),\
                            ((DEM_arr[i][j] - DEM_arr[i+1][j-1])/1.41,5),(DEM_arr[i][j] - DEM_arr[i+1][j],6),((DEM_arr[i][j] - DEM_arr[i+1][j+1])/1.41,7))
      Flow_arr[i][j] = dirn
      if value <= 0:
        Flow_arr[i][j] = 8

  # Calculate flow accumulation by calling Generate_River function
  print "Performing Flow accumulation"
  River_arr  = Flow_accum.Generate_River( Flow_arr,River_arr,DEM_arr)

  Distance_arr = city_block_dist_erosion.CityBlock(River_arr)
  # Create a mask for differnet distances used for DEM erosion
  print "Eroding DEM"
  mask4 = [ Distance_arr <= 15 ]
  mask5 = [ Distance_arr > 3 ]
  mask3 = [Distance_arr == 3]
  mask2 = [Distance_arr == 2]
  mask1 = [Distance_arr == 1]
  mask0 = [Distance_arr == 0]
  max_flow_accum = numpy.max(River_arr)

# TODO - maybe change the block below - have already combined the DEMs. Weight erosion more simply
  for i in range(0,x_len):
    for j in range(0,y_len):
      #Erode the landscape using diffent weighing factor for different distances from 
      #river while combining 3 DEM's 
      if mask0[0][i][j] == True:
        DEM_arr[i][j] = 0.3*DEM_arr[i][j] + 0.45*DEM_arr2[i][j] + 0.19*DEM_arr3[i][j]
      elif mask1[0][i][j] == True:
        DEM_arr[i][j] = 0.3*DEM_arr[i][j] + 0.46*DEM_arr2[i][j] + 0.20*DEM_arr3[i][j]
      elif mask2[0][i][j] == True:
        DEM_arr[i][j] = 0.3*DEM_arr[i][j] + 0.46*DEM_arr2[i][j] + 0.21*DEM_arr3[i][j]
      elif mask3[0][i][j] == True:
        DEM_arr[i][j] = 0.3*DEM_arr[i][j] + 0.46*DEM_arr2[i][j] + 0.23*DEM_arr3[i][j]
      elif mask4[0][i][j] == True and mask5[0][i][j] == True:
        DEM_arr[i][j] = 0.3*DEM_arr[i][j] + 0.47*DEM_arr2[i][j] + 0.23*DEM_arr3[i][j]
      else:     
        DEM_arr[i][j] = 0.3*DEM_arr[i][j] + 0.50*DEM_arr2[i][j] + 0.25*DEM_arr3[i][j]

#Output different statistics for display and further use
  print "printing statistics ...see the Output Folder"
  numpy.save("River.npy",River_arr) 
  numpy.save("DEM.npy",DEM_arr)
  pylab.imsave("Output/River",River_arr)
  pylab.imsave("Output/Catchment",Found_arr)
  pylab.imsave("Output/CatchmentBoundary",Catchment_boundary_arr)
  pylab.imsave("Output/Combined_eroded_DEM",DEM_arr)
  pylab.imsave("Output/RiverDistance",Distance_arr)

  return DEM_arr