Skip to content

Commit

Permalink
add plot scripts back
Browse files Browse the repository at this point in the history
  • Loading branch information
tannguyen153 committed Nov 19, 2024
1 parent 3d81ec9 commit dc45f49
Show file tree
Hide file tree
Showing 2 changed files with 215 additions and 0 deletions.
61 changes: 61 additions & 0 deletions utilities/plotMovie/createMov.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
#!/bin/bash
module load python

GROUP="FIPS"
ZOOM="NO"
BAYAREA="NO"
for i in "$@"; do
case $i in
-c=*|--censusMap=*)
CENSUS="${i#*=}"
shift # past argument=value
;;
-i=*|--infectionCases=*)
INFECTION="${i#*=}"
shift # past argument=value
;;
-m=*|--plotMode=*) #CUML/DAILY
OUTPUT_MODE="${i#*=}"
shift # past argument=value
;;
-n=*|--normalize=*) #RAW (no normalization), POP (normalize to population)
NORM="${i#*=}"
shift # past argument=value
;;
-g=*|--group=*) #group data to a higher level (FIPS and GROUP are 2 options for now)
GROUP="${i#*=}"
shift # past argument=value
;;
-z=*|--zoomin=*) #zoom in towards a location, format: "startTime, stopTime, target x, target y, zoomFactor"
ZOOM="${i#*=}"
shift # past argument=value
;;
-b=*|--bayAreaDataFormat=*)
BAYAREA="${i#*=}"
shift # past argument=value
;;
-*|--*)
echo "Unknown option $i"
exit 1
;;
*)
;;
esac
done

echo "PATH TO INFECTION CASES: ${INFECTION}"
echo "PATH TO CENSUS MAP: ${CENSUS}"
echo "MODE TO PLOT: ${OUTPUT_MODE}"
echo "NORMALIZE TO: ${NORM}"
echo "GROUP TO (DEFAULT: FIPS): ${GROUP}"
echo "ZOOM IN (DEFAULT: NO): ${ZOOM}"
echo "BAY AREA DATA FORMAT (DEFAULT: NO): ${BAYAREA}"

#plot everyday's cases on a cencus map
python3 plotCases.py ${INFECTION} ${CENSUS} ${OUTPUT_MODE} ${NORM} ${GROUP} ${ZOOM} ${BAYAREA}

#create movie
ffmpeg -framerate 1 -i "casefile%05d.png" -c:v libx264 -r 30 -pix_fmt yuv420p movie.mp4

#remove temporary files
rm *.png
154 changes: 154 additions & 0 deletions utilities/plotMovie/plotCases.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
import matplotlib as mpl
import matplotlib.pyplot as plt
from mpl_toolkits.axes_grid1.inset_locator import inset_axes
from matplotlib import colors
from matplotlib import cm
import os
import fiona
import geopandas as geopd
import pysal as ps
import shapefile
import pandas as pd
from shapely.geometry import shape
import numpy as np
import os
import sys
import re

argList= sys.argv[1:]
zoom=""
group=""
BayAreaDataFormat=""
if(len(argList)<5): #5 is the minimum mandatory arguments
print("Some mandatory argument is missing")
exit
if len(argList)>= 1: infCasesDir= argList[0]+"/"
if len(argList)>= 2: CensusDir = argList[1]+"/"
if len(argList)>= 3: outputMetric = argList[2]
if len(argList)>= 4: datanorm = argList[3]
if len(argList)>= 5: group = argList[4]
if len(argList)>= 6: zoom = argList[5] #format: "startTime, stopTime, target x, target y, zoomFactor"
if len(argList)>= 7: BayAreaDataFormat= argList[6]

gdf = geopd.GeoDataFrame(columns=["STATEFP00", "COUNTYFP00", "TRACTCE00", "CTIDFP00", "NAME00", "NAMELSAD00", "MTFCC00", "FUNCSTAT00", "ALAND00", "AWATER00", "INTPTLAT00", "INTPTLON00", "geometry"])
#for Bay Area dataset, use the following format:
if(BayAreaDataFormat=="YES"): gdf = geopd.GeoDataFrame(columns=["geoid", "name_", "namelsad", "mtfcc", "funcstat", "aland", "awater", "intptlat", "intptlon", "SHAPE_Leng", "SHAPE_Area"])

infCasesFiles= [os.path.join(infCasesDir, f) for f in os.listdir(infCasesDir) if f.endswith(".csv")]

for file in os.listdir(CensusDir):
filename = CensusDir + file + "/" + file
myshp = open(filename+".shp", "rb")
mydbf = open(filename+".dbf", "rb")
myprj = open(filename+".prj", "rb")
r = shapefile.Reader(shp=myshp, dbf=mydbf, prj=myprj)
attributes, geometry = [], []
field_names = [field[0] for field in r.fields[1:]]
for row in r.shapeRecords():
geometry.append(shape(row.shape.__geo_interface__))
attributes.append(dict(zip(field_names, row.record)))
df = geopd.GeoDataFrame(data = attributes, geometry = geometry)
gdf= gdf._append(df)
r.close()

if(BayAreaDataFormat=="NO"): gdf['fips'] = gdf["CTIDFP00"].astype(int)
else: gdf['fips'] = gdf["geoid"].astype(int)
gdf["county"]= gdf["fips"]//1000000
gdf0= gdf.copy()
gdf1= gdf.copy()
gdf0['per'] = 0.0
gdf1['per'] = 0.0
gdf1.set_index('fips',inplace=True)


sorted_infCasesFiles= sorted(infCasesFiles, key=lambda x: int( re.findall('\d+', x)[0]))
for caseFile in sorted_infCasesFiles:
idx = int(re.findall('\d+', caseFile)[0])
print("processing file", caseFile)
df000 = pd.read_csv(caseFile, header=None, names=["fips", "per"], dtype={"fips":int, "per":float})
#df000.set_index("fips",inplace=True)
gdf_join = pd.merge(gdf,df000, left_on="fips", right_on="fips", how='inner')
if(group=="COUNTY"):
if(datanorm=="RAW"):
df000["county"]= df000["fips"]//1000000
df000.drop("fips", inplace=True, axis=1)
df000= df000.groupby("county").sum()
gdf_join = pd.merge(gdf,df000, left_on='county', right_on='county', how='inner')
#gdf_join.set_index('fips',inplace=True)
columns= gdf1.columns.values
columns= columns[:-1].tolist() #exclude per
if(outputMetric=="DAILY"):
gdf1= pd.concat([gdf0, gdf_join]).groupby(columns).sum().reset_index()
if(outputMetric=="CUML"):
gdf1= pd.concat([gdf0, gdf_join]).groupby(columns).sum().reset_index()

fig, ax = plt.subplots(figsize=(10,10))

gdfplot= geopd.GeoDataFrame(gdf1)
#use cmap with a norm to convert a number to RGB
#two slope norm
#set center to 0, adjust the negative vmin to control how fast color changes from 0 to vmax
if(datanorm=="RAW"):
vmin = -1.0
vmax = 25
norm = colors.TwoSlopeNorm(vmin=vmin, vcenter=0.000, vmax=vmax)
cmap = cm.cool
sm = plt.cm.ScalarMappable(cmap=cmap, norm=norm)
gdfplot["per"] = gdfplot["per"] + 1 #avoid log(0)
gdfplot["per"] = np.log2(gdfplot["per"])
plt.colorbar(sm, ax=ax, ticks=np.linspace(0, 25, 6), label="Log2 Cumulative Cases", orientation="vertical")
else:
if(datanorm=="POP"):
vmin = -10.0
vmax = 1.0
norm = colors.TwoSlopeNorm(vmin=vmin, vcenter=0.000, vmax=vmax)
cmap = cm.cool
sm = plt.cm.ScalarMappable(cmap=cmap, norm=norm)
plt.colorbar(sm, ax=ax, ticks=np.linspace(0, 1, 11), label="Cumulative Cases per Population", orientation="vertical")
else:
print("INPUT METRIC NOT PROVIDED", norm)
exit
ax.xaxis.set_ticks_position('top')
ax.set(aspect='equal', xticks=[], yticks=[])

gdfplot.plot(column= 'per', ax = ax, norm=norm, cmap=cmap, lw=3)#, edgecolor='black',)#, legend=False)

#adjust the position and zoom in
if(zoom!="NO"):
startTime, stopTime, targetX, targetY, zoomFactor= zoom.split(',')
startTime= int(startTime)
stopTime= int(stopTime)
shiftTime=10 #we need 10 days to smoothly shift to the target position
targetX= float(targetX)
targetY= float(targetY)
zoomFactor= float(zoomFactor)
xrate= (0.5-targetX)/10
yrate= (0.5-targetY)/10
zoomrate= (1.0-1.0/zoomFactor)/(stopTime-shiftTime-startTime)

ylim = ax.get_ylim()
xlim = ax.get_xlim()
if(idx>=startTime and idx<(startTime+shiftTime)):
#gradually shift to the interested local area
ax.set_xlim((xlim[0]-(xlim[1]-xlim[0])*xrate*(idx-startTime), xlim[1]-(xlim[1]-xlim[0])*xrate*(idx-startTime)))
ax.set_ylim((ylim[0]-(ylim[1]-ylim[0])*yrate*(idx-startTime), ylim[1]-(ylim[1]-ylim[0])*yrate*(idx-startTime)))
if(idx>=(startTime+shiftTime) and idx<stopTime):
#now all figures start looking at the interested local area
ax.set_xlim((xlim[0]-(xlim[1]-xlim[0])*xrate*shiftTime, xlim[1]-(xlim[1]-xlim[0])*xrate*shiftTime) )
ax.set_ylim((ylim[0]-(ylim[1]-ylim[0])*yrate*shiftTime, ylim[1]-(ylim[1]-ylim[0])*yrate*shiftTime) )
#we want to zoom in a little more
ylim = ax.get_ylim()
xlim = ax.get_xlim()
ax.set_xlim((xlim[0]+(xlim[1]-xlim[0])*zoomrate*(idx-startTime-shiftTime)/2, xlim[1]-(xlim[1]-xlim[0])*zoomrate*(idx-startTime-shiftTime)/2) )
ax.set_ylim((ylim[0]+(ylim[1]-ylim[0])*zoomrate*(idx-startTime-shiftTime)/2, ylim[1]-(ylim[1]-ylim[0])*zoomrate*(idx-startTime-shiftTime)/2) )
if(idx>=stopTime):
#stay exactly where last figure was. No more shifting, no more zooming
ax.set_xlim((xlim[0]-(xlim[1]-xlim[0])*xrate*shiftTime, xlim[1]-(xlim[1]-xlim[0])*xrate*shiftTime) )
ax.set_ylim((ylim[0]-(ylim[1]-ylim[0])*yrate*shiftTime, ylim[1]-(ylim[1]-ylim[0])*yrate*shiftTime) )
ylim = ax.get_ylim()
xlim = ax.get_xlim()
ax.set_xlim((xlim[0]+(xlim[1]-xlim[0])*zoomrate*(stopTime-shiftTime-startTime)/2, xlim[1]-(xlim[1]-xlim[0])*zoomrate*(stopTime-shiftTime-startTime)/2 ))
ax.set_ylim((ylim[0]+(ylim[1]-ylim[0])*zoomrate*(stopTime-shiftTime-startTime)/2, ylim[1]-(ylim[1]-ylim[0])*zoomrate*(stopTime-shiftTime-startTime)/2 ))
output= "casefile"+str(idx+1).zfill(5)+".png"
plt.savefig(output)
plt.close()

0 comments on commit dc45f49

Please sign in to comment.