Advertisement
BrianMakesGames

Heatmap Generator

Oct 17th, 2018
421
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. # @author: Brian Keschinger
  2. import matplotlib.pyplot as plt
  3. import numpy as np
  4. import seaborn as sns
  5. import pandas as pd
  6.  
  7. # Start utility functions
  8. '''-------------------------------------------------------
  9. Function: ResetPlot
  10. Description: Clears the figure being used in pyplot and sets up our dimensions, axes, image, and layout.
  11. ----------------------------------------------------------'''
  12. def ResetPlot():
  13.     global ax
  14.     global img    
  15.     # Clear the current plot so we can reuse it  
  16.     plt.clf()
  17.  
  18.     # Turn off auto scaling and set the limits
  19.     ax = plt.gca()
  20.     ax.set_autoscale_on(False)
  21.    
  22.     # hide both axes
  23.     ax.axes.get_xaxis().set_visible(False)
  24.     ax.axes.get_yaxis().set_visible(False)
  25.  
  26.     # Set axis limits [xmin, xmax, ymin, ymax]
  27.     plt.axis([1, 1920, 1, 1080])
  28.  
  29.     # flipud(): flips an array in the "up/down" direction so it's flipping the image
  30.     # Then we say that the plot origin is lower which also flips the image
  31.     # The result is a correctly shown image with a coordinate system origin of the lower left
  32.     plt.imshow(np.flipud(img), origin='lower')
  33.  
  34.     # We're hiding the axes and their labels anyway so this will auto fit nicely to the figure area
  35.     plt.tight_layout()
  36.  
  37.  
  38. '''----------------------------------------------------------
  39. Function: ConvertDataToAdjustedGrid
  40. Description: Used to convert the image's pixel-based grid to a new grid size
  41. @param[in] dataFrame: Data Frame that contains a type column that contains kills and deaths
  42. @param[in] cellSize: int that's the new grid cell size used to convert the 1920x1080 grid
  43. @return[out] adjustedGrid: a 2D Array consisting of summed integer values that will act as the converted grid
  44. -------------------------------------------------------------'''
  45. def ConvertDataToAdjustedGrid(dataFrame, cellSize):    
  46.     # Using the gridSize find out how many rows and columns the new array and grid will be    
  47.     xAxisSize = int(1920 / cellSize)
  48.     yAxisSize = int(1080 / cellSize)
  49.  
  50.     # Create a fixed-size array that starts with all zeros
  51.     adjustedGrid = np.zeros((yAxisSize, xAxisSize))
  52.  
  53.     # Loop through all the rows of the data
  54.     # Convert the raw pixel coordinates to the adjusted grid
  55.     # Add 1 for any kill and subtract 1 for deaths  
  56.     for index, row in dataFrame.iterrows():
  57.         xCell = int(np.floor(row.x / cellSize))
  58.         yCell = (yAxisSize-1) - int(np.floor(row.y / cellSize)) # 0,0 for a 2D array will be the top left so we want to flip the yAxis
  59.         adjustedGrid[yCell][xCell] += 1 if (row.type == 'k') else -1
  60.    
  61.     return adjustedGrid
  62.  
  63. '''----------------------------------------------------------
  64. Function: CreateAndExportHeatmap
  65. Description: Used to create and save to disk a heatmap from a dataset
  66. @param[in] fileName: string that will be used to save the image to disc and name the graph
  67. @param[in] dataFrame: Data Frame that contains a type column that contains kills and deaths
  68. @param[in] cellSize: int that's the new grid cell size used to convert the 1920x1080 grid
  69. -------------------------------------------------------------'''
  70. def CreateAndExportHeatmap(fileName, dataFrame, cellSize):
  71.     global ax    
  72.     ResetPlot()    
  73.     newAdjustedGrid = ConvertDataToAdjustedGrid(dataFrame, cellSize)
  74.    
  75.     # Find the min and max value in the array
  76.     minVal = np.amin(newAdjustedGrid)
  77.     maxVal = np.amax(newAdjustedGrid)
  78.    
  79.     # Between the min and max find our new bounds
  80.     upperBound = max(abs(minVal), abs(maxVal))
  81.    
  82.     # Using the upperBound we found, set the color bounds from -upperBound to +upperBound so that white sits at 0 properly
  83.     sns_heatmap = sns.heatmap(newAdjustedGrid, cmap='seismic_r', center=0.0, linewidths=.5, vmin=-upperBound, vmax=upperBound)
  84.  
  85.     # Set the plot title from the fileName but replace dashes with spaces
  86.     ax.set_title(fileName.replace('-',' '))
  87.  
  88.     # Save the image to disk (directory must be created)
  89.     # We're using 500 dpi because the original figure size is small and 500 will push the actual graph to be larger than 1920x1080
  90.     # We'll pull this into PhotoShop and overlay it onto our map with some nice opacities, etc.
  91.     fig = sns_heatmap.get_figure()
  92.     fig.savefig('Exported_Graphs/' + fileName +'.png', dpi=500)
  93. # End utility functions
  94.    
  95. # Read the CSVs from disk
  96. CTF_data = pd.read_csv("Playtest_Data/6-7_Playtest_CTF.csv")
  97. BMB_data = pd.read_csv("Playtest_Data/6-7_Playtest_Bomb.csv")
  98.  
  99. # data[key] == something returns a boolean value
  100. # by insterting that value into data.loc it returns all the rows where that is true
  101. CTF_deathPositions = CTF_data.loc[CTF_data['type']=='d']
  102. CTF_killPositions = CTF_data.loc[CTF_data['type']=='k']
  103.  
  104. # Import Map Background
  105. img = plt.imread("Source_Images/Map_Overhead.png")    
  106.    
  107. # Because everything is plotted on an image of 1920x1080, we'll need a common factor to be the new cell size
  108. # 1, 2, 3, 4, 5, 6, 8, 10, 12, 15, 20, 24, 30, 40, 60, 120
  109. newGridCellSize = 120
  110.  
  111. CreateAndExportHeatmap('CTF-All-Kills-and-Deaths-Heatmap', CTF_data, newGridCellSize)
  112. CreateAndExportHeatmap('BMB-All-Kills-and-Deaths-Heatmap', BMB_data, newGridCellSize)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement