diff --git a/InteractiveProgrammingProjectWriteup.pdf b/InteractiveProgrammingProjectWriteup.pdf new file mode 100644 index 0000000..39bfccf Binary files /dev/null and b/InteractiveProgrammingProjectWriteup.pdf differ diff --git a/README.md b/README.md index 61ec120..ee54ff5 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,5 @@ # InteractiveProgramming This is the base repo for the interactive programming project for Software Design, Spring 2016 at Olin College. + + +To run code: simply run WH_ShapeMap.py to get the output graph (references WH_Freshmen.csv). See writeup document for more details. diff --git a/WH_Freshmen.csv b/WH_Freshmen.csv new file mode 100644 index 0000000..7ebcab7 --- /dev/null +++ b/WH_Freshmen.csv @@ -0,0 +1,51 @@ +101,R2,N/A,N/A,N/A,N/A,,,,, +102,Gwyn and Regina,Female,1,2,3,,,,, +103,Emily Y. and Jingyi,Female,12,2.5,2,,"J,E","12,12","3,2","1,3" +104,Andrew P. and Sam,Male,1,2,2,,"S,A","1,1","2,2","1,3" +105,Bryan and Nathan,Male,1,2,2,,,,, +106,Emma and Erica,Female,,,,,,,, +107,Alex S. and David,Male,,,,,,,, +109,[Nick Tatar],N/A,N/A,N/A,N/A,,,,, +110,[Nick Tatar],N/A,N/A,N/A,N/A,,,,, +118,[Kitchen],N/A,N/A,N/A,N/A,,,,, +120,[Gym],N/A,N/A,N/A,N/A,,,,, +123,[Ball Room],N/A,N/A,N/A,N/A,,,,, +125,[Service Room],N/A,N/A,N/A,N/A,,,,, +124,Anna,Female,,,,,,,, +126,Diego and Sean,Male,11,2,4,,,,, +127,Annie and Tehya,Female,11,2,3,,,,, +128,Louise and Katya,Nonbinary/Female,1,2.5,2,,"L,K","11,3","3,2","1,3" +129,Carl and Kevin G.,Male,2,2,2,,,,, +130,Danny and Will,Male,12,2,2,,,,, +131,Alex H. and Leon,Male,,,,,,,, +201,Eric and Max S.,Male,1,2.5,1,,"M,E","1,1","3,2","1,1" +202,Dhash and Taylor,Male,3,2,2,,,,, +203,Jamie and Jeremy,Male,2,2,3,,,,, +204,Margo and Nicole,Female,1,3,1,,,,, +205,Lauren G. and Uma,Female,2,2.5,2,,"L,U","2,2","3,2","2,2" +207,Claire and Liv,Female,12,1,3,,,,, +209,John Moreland and Joseph,Male,12,3,1,,,,, +210,Jared and Max D.,Male,1,2,1,,,,, +211,Katie and Serena,Female,2.5,3,2.5,,"S,K","1,4","3,3","2,3" +212,Ariana and Emily K.,Female,12,2,3.5,,"A,E","12,12","2,2","4,3" +213,Linnea and Mary,Female,12.5,2,2,,"M,L","1,12","2,2","3,1" +214,John Mathai and Justin,Male,12,3,1,,,,, +215,Daniel D. and Steven,Male,2.5,2,2,,"S,D","4,1","2,2","0,2" +218,R2,N/A,N/A,N/A,N/A,,,,, +220,R2,N/A,N/A,N/A,N/A,,,,, +223,Harper and Paige,Female,11,2,3,,,,, +224,Charlie and Rachel,Female,1.5,2,2.5,,"R,C","1,2","2,2","2,3" +225,Apurva and Sara,Female,1,2,3,,,,, +226,Jonah,Male,,,,,,,, +227,Matt and Arpan,Male,2,2,3.5,,"M, A","2,2","2,2","3,4" +228,Mica and Min,Female,11,2,3,,,,, +229,Lydia and Kim,Female,12.5,2.5,4,,"K,L","1,12","2,3","3,5" +230,Andrew and Hunter,Male,,,,,,,, +231,Bill and Isaac,Male,1.5,2,2.5,,"I,B","1,2","2,2","3,2" +301,Chloe and Kaitlyn,Female,11.5,1.5,3,,"K,C","12, 11","2,1","0,3" +302,Audrey and Izzy,Female,12.5,2.5,1,,"A,I","1,12","2,3","0,1" +303,Ian and Kevin Z.,Male,2,2,3,,,,, +304,Cedric and Duncan,Male,,,,,,,, +305,Lauren P. and March,Female,1.5,2.5,4,,"L,M","2,1","2,3","4,4" +306,Coleman and Max W.,Male,,,,,,,, +307,Jonathan and Sung,Male,12,2.5,1.5,,"S,J","1,11","3,2","2,1" diff --git a/WH_Interactive_Map.py b/WH_Interactive_Map.py new file mode 100644 index 0000000..2350ce1 --- /dev/null +++ b/WH_Interactive_Map.py @@ -0,0 +1,128 @@ +from bokeh.models import BoxSelectTool, BoxZoomTool, LassoSelectTool, HoverTool, Quad +from bokeh.plotting import figure, output_file, show, gridplot, ColumnDataSource +from bokeh.models.widgets import Dropdown, Panel, Tabs, CheckboxButtonGroup, RadioGroup +from bokeh.io import output_file, show, vform, save +import csv + +#PROJECT OVERVIEW: +#Create an interactive map of West Hall showing hallway culture via gender distribution, sleeping habits, time spent in hallways, etc. +#(If we hear back from STAR, we'll also have data on how people move from year to year, which will be awesome to implement) + +#PROGRESS: +#currently outputs to an html file which has 3 tabs - WH1, WH2, and WH3 +#rooms are currently blue squares, have hover functionality with correct labels but no data +#Also have buttons that are currently nonfunctional but are planned to be able to display different color coordinations for each room. +#Initializes and draws all rooms from a .csv file with data from survey sent to first years. + +#NEXT STEPS: +#Get more room data from people (keep collecting survey responses) +#Draw rooms in correct places +#Make import for roommate names work correctly +#Make hover display room number and inhabitant names instead of '???' +#Make buttons functional + #figure out how to make buttons active + #make metric for color changing and coordination + + +# output to static HTML file +output_file("WH_Firstyears.html") + +class Room(object): + def __init__(self, roomNum='000', roommates='[Roommate Names Here]', gender='[Some Gender Here]', bedtime=0, lightsleep=0, halltime=0, top=1, bottom=0, left=0, right=1): + self.roomNum = roomNum + self.roommates = roommates + self.gender = gender + self.bedtime = bedtime + self.lightsleep = lightsleep + self.halltime = halltime + self.top = top + self.bottom = bottom + self.left = left + self.right = right + + def __str__(self): + return 'Room Number: %s / Current Inhabitants: %s / Gender: %s / Average Bedtime: %s' %(self.roomNum, self.roommates, self.gender, self.bedtime) + + def drawRoom(self): + if int(self.roomNum)<200: + #draw on first floor + rooms1 = p1.quad(top=self.top,bottom=self.bottom, left=self.left, right=self.right, + nonselection_fill_alpha=0.01, + nonselection_fill_color=None, + nonselection_line_color="firebrick", + nonselection_line_alpha=1.0, + selection_color="blue", + selection_fill_alpha=.5) + + elif int(self.roomNum)<300: + #draw on second floor + rooms2 = p2.quad(top=self.top,bottom=self.bottom, left=self.left, right=self.right, + nonselection_fill_alpha=0.01, + nonselection_fill_color=None, + nonselection_line_color="firebrick", + nonselection_line_alpha=1.0, + selection_color="blue", + selection_fill_alpha=.5) + else: + #draw on third floor + rooms3 = p3.quad(top=self.top,bottom=self.bottom, left=self.left, right=self.right, + nonselection_fill_alpha=0.01, + nonselection_fill_color=None, + nonselection_line_color="firebrick", + nonselection_line_alpha=1.0, + selection_color="blue", + selection_fill_alpha=.5) + + +TOOLS = "box_zoom,box_select,resize,reset,hover,tap" + +#draws first floor of WH +p1 = figure(plot_width=400, plot_height=400, tools=TOOLS,title="West Hall First Floor") +tab1 = Panel(child=p1, title="WH1") +p1.segment(x0=[1, 1, 1, 6], y0=[1, 6, 1, 1], x1=[6, 6, 1, 6], + y1=[1, 6, 6, 6], color="#F4A582", line_width=3) +p1.select_one(HoverTool).tooltips = [('Room Number','@roomNum'),('Inhabitants','@roommates')] + +#draws second floor of WH +p2 = figure(plot_width=400, plot_height=400, tools=TOOLS,title="West Hall Second Floor") +tab2 = Panel(child=p2, title="WH2") +p2.segment(x0=[1, 1, 1, 6], y0=[1, 6, 1, 1], x1=[6, 6, 1, 6], + y1=[1, 6, 6, 6], color="#F4A582", line_width=3) +p2.select_one(HoverTool).tooltips = [('Room Number','@roomNum'),('Inhabitants','@roommates')] + +#draws third floor of WH +p3 = figure(plot_width=400, plot_height=400, tools=TOOLS,title="West Hall Third Floor") +tab3 = Panel(child=p3, title="WH3") +p3.segment(x0=[1, 1, 1, 6], y0=[1, 6, 1, 1], x1=[6, 6, 1, 6], + y1=[1, 6, 6, 6], color="#F4A582", line_width=3) +p3.select_one(HoverTool).tooltips = [('Room Number','@roomNum'),('Inhabitants','@roommates')] + + +#Pull data from csv file and create Room objects from it! +with open('WH_Freshmen.csv') as csvfile: + freshmen_data = csv.reader(csvfile, delimiter=',', quotechar='\"') + #roomList = [] + for row in freshmen_data: + roomA = Room() #initializes a new Room for each row in the csv data file + roomA.roomNum = row[0] + roomA.roomates = row[1] #not working for some reason? + roomA.gender = row[2] + roomA.bedtime = row[3] + roomA.lightsleep = row[4] + roomA.halltime = row[5] + roomA.top = 2 + roomA.bottom = 1 + roomA.left = 1 + roomA.right = 2 + roomA.drawRoom() + #roomList.append(roomA) #creates list of all Room objects + +dropdown_choices = [("Gender", "gender"), ("Bedtime", "bedtime"), ("Light Sleeper", "lightsleep"), ("Time in Hallway", "halltime")] +dropdown = Dropdown(label="Hallway Metrics", type="warning", menu=dropdown_choices) + +tabs = Tabs(tabs=[tab1, tab2, tab3]) +layout = vform(dropdown, tabs) + +# show the results +save(tabs) +show(layout) \ No newline at end of file diff --git a/WH_ServerExperimentation.py b/WH_ServerExperimentation.py new file mode 100644 index 0000000..c777bbf --- /dev/null +++ b/WH_ServerExperimentation.py @@ -0,0 +1,137 @@ +from bokeh.models import BoxSelectTool, BoxZoomTool, LassoSelectTool, HoverTool, Quad +from bokeh.plotting import figure, output_file, show, gridplot, ColumnDataSource, output_server +from bokeh.models.widgets import Dropdown, Panel, Tabs, CheckboxButtonGroup, RadioGroup +from bokeh.io import output_file, show, vform, save +import csv + +#PROJECT OVERVIEW: +#Create an interactive map of West Hall showing hallway culture via gender distribution, sleeping habits, time spent in hallways, etc. +#(If we hear back from STAR, we'll also have data on how people move from year to year, which will be awesome to implement) + +#PROGRESS: +#currently outputs to an html file which has 3 tabs - WH1, WH2, and WH3 +#rooms are currently blue squares, have hover functionality with correct labels but no data +#rooms are 1 unit squares with an x position between 0 and 11 and a y position between 1 and 13. +#Also have buttons that are currently nonfunctional but are planned to be able to display different color coordinations for each room. +#Initializes and draws all rooms from a .csv file with data from survey sent to first years. + +#NEXT STEPS: +#Get more room data from people (keep collecting survey responses) +#Draw rooms in correct places +#Make import for roommate names work correctly +#Make hover display room number and inhabitant names instead of '???' +#Make buttons functional + #figure out how to make buttons active + #make metric for color changing and coordination + #bokeh server things + + +# output to static HTML file + +class Room(object): + def __init__(self, roomNum='000', roommates='[Roommate Names Here]', gender='[Some Gender Here]', bedtime=0, lightsleep=0, halltime=0, top=1, bottom=0, left=0, right=1): + self.roomNum = roomNum + self.roommates = roommates + self.gender = gender + self.bedtime = bedtime + self.lightsleep = lightsleep + self.halltime = halltime + self.top = top + self.bottom = bottom + self.left = left + self.right = right + self.gendercolor = "green" + self.bedtimecolor = "blue" + self.color = + + def __str__(self): + return 'Room Number: %s / Current Inhabitants: %s / Gender: %s / Average Bedtime: %s' %(self.roomNum, self.roommates, self.gender, self.bedtime) + + def drawRoom(self): + if int(self.roomNum)<200: + #draw on first floor + rooms1 = p1.quad(top=self.top,bottom=self.bottom, left=self.left, right=self.right, + nonselection_fill_alpha=0.01, + nonselection_fill_color=None, + nonselection_line_color="firebrick", + nonselection_line_alpha=1.0, + selection_color="blue", + selection_fill_alpha=.5) + + elif int(self.roomNum)<300: + #draw on second floor + rooms2 = p2.quad(top=self.top,bottom=self.bottom, left=self.left, right=self.right, + nonselection_fill_alpha=0.01, + nonselection_fill_color=None, + nonselection_line_color="firebrick", + nonselection_line_alpha=1.0, + selection_color="blue", + selection_fill_alpha=.5) + else: + #draw on third floor + rooms3 = p3.quad(top=self.top,bottom=self.bottom, left=self.left, right=self.right, + nonselection_fill_alpha=0.01, + nonselection_fill_color=None, + nonselection_line_color="firebrick", + nonselection_line_alpha=1.0, + selection_color="blue", + selection_fill_alpha=.5) + +TOOLS = "box_zoom,box_select,resize,reset,hover,tap" + +#draws first floor of WH +p1 = figure(plot_width=400, plot_height=400, tools=TOOLS,title="West Hall First Floor") + +p1.segment(x0=[0, 4, 4, 7, 7, 11, 11, 7, 7, 4, 4, 0], y0=[13, 13, 12, 12, 13, 13, 10, 10, 1, 1, 10, 10], + x1=[4, 4, 7, 7, 11, 11, 7, 7, 4, 4, 0, 0], y1=[13, 12, 12, 13, 13, 10, 10, 1, 1, 10, 10, 13], color="green", line_width=3) +p1.select_one(HoverTool).tooltips = [('Room Number','@roomNum'),('Inhabitants','@roommates')] + +#draws second floor of WH +p2 = figure(plot_width=400, plot_height=400, tools=TOOLS,title="West Hall Second Floor") + +p2.segment(x0=[0, 4, 4, 7, 7, 11, 11, 7, 7, 4, 4, 0], y0=[13, 13, 12, 12, 13, 13, 10, 10, 1, 1, 10, 10], + x1=[4, 4, 7, 7, 11, 11, 7, 7, 4, 4, 0, 0], y1=[13, 12, 12, 13, 13, 10, 10, 1, 1, 10, 10, 13], color="#F4A582", line_width=3) +p2.select_one(HoverTool).tooltips = [('Room Number','@roomNum'),('Inhabitants','@roommates')] + +#draws third floor of WH +p3 = figure(plot_width=400, plot_height=400, tools=TOOLS,title="West Hall Third Floor") + +p3.segment(x0=[0, 4, 4, 7, 7, 11, 11, 7, 7, 4, 4, 0], y0=[13, 13, 12, 12, 13, 13, 10, 10, 1, 1, 10, 10], + x1=[4, 4, 7, 7, 11, 11, 7, 7, 4, 4, 0, 0], y1=[13, 12, 12, 13, 13, 10, 10, 1, 1, 10, 10, 13], color="#F4A582", line_width=3) +p3.select_one(HoverTool).tooltips = [('Room Number','@roomNum'),('Inhabitants','@roommates')] + + +#Pull data from csv file and create Room objects from it! +with open('WH_Freshmen.csv') as csvfile: + freshmen_data = csv.reader(csvfile, delimiter=',', quotechar='\"') + #roomList = [] + for row in freshmen_data: + roomA = Room() #initializes a new Room for each row in the csv data file + roomA.roomNum = row[0] + roomA.roomates = row[1] #not working for some reason? + roomA.gender = row[2] + roomA.bedtime = row[3] + roomA.lightsleep = row[4] + roomA.halltime = row[5] + roomA.top = 13 + roomA.bottom = 12 + roomA.left = 0 + roomA.right = 1 + roomA.color = roomA.gendercolor + roomA.drawRoom() + #roomList.append(roomA) #creates list of all Room objects + +dropdown_choices = [("Gender", "gender"), ("Bedtime", "bedtime"), ("Light Sleeper", "lightsleep"), ("Time in Hallway", "halltime")] +dropdown = Dropdown(label="Hallway Metrics", type="warning", menu=dropdown_choices) + +#creating a callback function for changing the color of the room +def callback(obj, attr, old, new): + ... +dropdown.on_change('selected', callback) + +tabs = Tabs(tabs=[Panel(child=p1, title="WH1"), Panel(child=p2, title="WH2"), Panel(child=p3, title="WH3")]) +layout = vform(dropdown, tabs) + +# show the results +save(tabs) +show(layout) \ No newline at end of file diff --git a/WH_ShapeMap.py b/WH_ShapeMap.py new file mode 100644 index 0000000..f3e6ada --- /dev/null +++ b/WH_ShapeMap.py @@ -0,0 +1,268 @@ +from bokeh.models import BoxSelectTool, BoxZoomTool, LassoSelectTool, HoverTool, Quad +from bokeh.plotting import figure, output_file, show, gridplot, ColumnDataSource, output_server, hplot +from bokeh.models.widgets import Dropdown, Panel, Tabs, CheckboxButtonGroup, RadioGroup +from bokeh.io import output_file, show, vform, save +import csv + +#PROJECT OVERVIEW: +#Create an interactive map of West Hall showing hallway culture via gender distribution, sleeping habits, time spent in hallways, etc. +#(If we hear back from STAR, we'll also have data on how people move from year to year, which will be awesome to implement) + +#PROGRESS: +#currently outputs to an html file which has 4 tabs displaying 3 floors of WH with data from freshmen +#rooms are currently blue squares, have hover functionality with correct labels but no data +#rooms are 1 unit squares with an x position between 0 and 11 and a y position between 1 and 13. +#Also have buttons that are currently nonfunctional but are planned to be able to display different color coordinations for each room. +#Initializes and draws all rooms in correct places from a .csv file with data from survey sent to first years. + +#NEXT STEPS: +#Get more room data from people (keep collecting survey responses) +#Make import for roommate names work correctly +#Make hover display given room number and inhabitant names instead of '???' + + + +# output to static HTML file +output_file("WH_Firstyears.html") + +class Room(object): + def __init__(self, roomNum='000', gender='[Some Gender Here]', bedtime=0, lightsleep=0, halltime=0, top=1, bottom=0, left=0, right=1): + self.roomNum = roomNum + self.gender = gender + self.bedtime = bedtime + self.lightsleep = lightsleep + self.halltime = halltime + self.top = top + self.bottom = bottom + self.left = left + self.right = right + + def __str__(self): + return 'Room Number: %s / Gender: %s / Average Bedtime: %s' %(self.roomNum, self.gender, self.bedtime) + + def findCoordinates(self): #defines positions for rooms + coordinates = [1,0,0,1] #top, bottom, left, right (respectively) + mod = int(self.roomNum)%100 #can do all floors at once + if mod<18: + if mod%2==1: + coordinates[0] = 13 + coordinates[1] = 12 + else: + coordinates[0] = 11 + coordinates[1] = 10 + + if mod==1 or mod==2: + coordinates[2] = 7 + coordinates[3] = 8 + elif mod==3 or mod==4: + coordinates[2] = 8 + coordinates[3] = 9 + elif mod==5 or mod==6: + coordinates[2] = 9 + coordinates[3] = 10 + elif mod==7: + coordinates[2] = 10 + coordinates[3] = 11 + elif mod==9 or mod==10: + if int(self.roomNum)==109 or int(self.roomNum)== 110: #special case: Nick Tatar + coordinates[2] = 0 + coordinates[3] = 4 + else: + coordinates[2] = 3 + coordinates[3] = 4 + elif mod==11 or mod==12: + coordinates[2] = 3 + coordinates[3] = 2 + elif mod==13 or mod==14: + coordinates[2] = 2 + coordinates[3] = 1 + elif mod==15: + coordinates[2] = 0 + coordinates[3] = 1 + elif mod>=18: + if mod%2==1: + coordinates[2] = 6 + coordinates[3] = 7 + else: + coordinates[2] = 4 + coordinates[3] = 5 + if mod==18: + coordinates[0] = 9 + coordinates[1] = 8 + elif mod==20: + coordinates[0] = 8 + coordinates[1] = 7 + elif mod==23 or mod==24: + coordinates[0] = 6 + coordinates[1] = 5 + elif mod==25 or mod==26: + coordinates[0] = 5 + coordinates[1] = 4 + elif mod==27 or mod==28: + coordinates[0] = 4 + coordinates[1] = 3 + elif mod==29 or mod==30: + coordinates[0] = 3 + coordinates[1] = 2 + elif mod==31: + coordinates[0] = 2 + coordinates[1] = 1 + return coordinates + + def findColors(self): + colors = [0,0,0,0]#gender, bedtime, light sleeper, hallway time (respectively) + + #gender + if self.gender=='Male': + colors[0] = '#663399' + elif self.gender=='Female': + colors[0] = '#FE5B35' + else: colors[0] = '#87CEEB' + + #bedtime + bedColors = {'11':'#E9E7F1','11.5':'#D4D0E4','12':'#BEB8D7','12.5':'#A9A1C9','1':'#9489BC','1.5':'#7E72AF','2':'#695AA1','2.5':'#534294','3':'#3E2B87'} + colors[1] = bedColors.get(self.bedtime, 'black') + + #light sleeper + lightsleepcolors = {'1':'#00B34D','1.5':'#00A145','2':'#008F3D','2.5':'#007D35','3':'#006B2E'} + colors[2] = lightsleepcolors.get(self.lightsleep,'black') + + #hallway time + hallwaycolors = {'1':'#CEF1F0','1.5':'#B6EBE9','2':'#9EE4E2','2.5':'#86DEDB','3':'#6DD7D3','3.5':'#55D0CC','4':'#3DCAC5','4.5':'#25CBE','5':'#0DBDB7'} + colors[3] = hallwaycolors.get(self.halltime,'black') + return colors + + def actuallyDrawRoom(self, plot, color, alpha): + plot.quad(top=self.top,bottom=self.bottom, left=self.left, right=self.right, + nonselection_fill_alpha=0.01, + fill_color=color, + alpha=alpha, + line_color=color, + hover_alpha = .7, + hover_fill_color=color, + nonselection_fill_color=color, + nonselection_line_color=color, + nonselection_line_alpha=1.0, + selection_color=color, + selection_fill_alpha=.5) + + + def drawRoom(self): + if self.gender == 'N/A': + gendercolor='grey' + bedtimecolor='grey' + lightsleepcolor='grey' + halltimecolor='grey' + alpha = .3 + else: + gendercolor=self.gendercolor + bedtimecolor=self.bedtimecolor + lightsleepcolor=self.lightsleepcolor + halltimecolor=self.halltimecolor + alpha = 1.0 + + if int(self.roomNum)<200: + #draw on first floor + self.actuallyDrawRoom(a1, gendercolor, alpha) + self.actuallyDrawRoom(b1, bedtimecolor, alpha) + self.actuallyDrawRoom(c1, lightsleepcolor, alpha) + self.actuallyDrawRoom(d1, halltimecolor, alpha) + + elif int(self.roomNum)<300: + #draw on second floor + self.actuallyDrawRoom(a2, gendercolor, alpha) + self.actuallyDrawRoom(b2, bedtimecolor, alpha) + self.actuallyDrawRoom(c2, lightsleepcolor, alpha) + self.actuallyDrawRoom(d2, halltimecolor, alpha) + else: + #draw on third floor + self.actuallyDrawRoom(a3, gendercolor, alpha) + self.actuallyDrawRoom(b3, bedtimecolor, alpha) + self.actuallyDrawRoom(c3, lightsleepcolor, alpha) + self.actuallyDrawRoom(d3, halltimecolor, alpha) +TOOLS = "box_zoom,box_select,resize,reset,tap" + +#creates the map in the shape of west hall for the given plot. +def make_mapshape(grid): + grid.xgrid.grid_line_color = None + grid.ygrid.grid_line_color = None + grid.segment(x0=[0, 4, 4, 7, 7, 11, 11, 7, 7, 4, 4, 0], y0=[13, 13, 12, 12, 13, 13, 10, 10, 1, 1, 10, 10], + x1=[4, 4, 7, 7, 11, 11, 7, 7, 4, 4, 0, 0], y1=[13, 12, 12, 13, 13, 10, 10, 1, 1, 10, 10, 13], color="#F4A582", line_width=3) + +#GENDER +#draws first floor of WH +a1 = figure(plot_width=400, plot_height=400, tools=TOOLS,title="West Hall First Floor") +make_mapshape(a1) +#draws second floor +a2 = figure(plot_width=400, plot_height=400, tools=TOOLS,title="West Hall Second Floor") +make_mapshape(a2) +#draws third floor +a3 = figure(plot_width=400, plot_height=400, tools=TOOLS,title="West Hall Third Floor") +make_mapshape(a3) +#BEDTIME +#draws first floor of WH +b1 = figure(plot_width=400, plot_height=400, tools=TOOLS,title="West Hall First Floor") +make_mapshape(b1) +#draws second floor of WH +b2 = figure(plot_width=400, plot_height=400, tools=TOOLS,title="West Hall Second Floor") +make_mapshape(b2) +#draws third floor of WH +b3 = figure(plot_width=400, plot_height=400, tools=TOOLS,title="West Hall Third Floor") +make_mapshape(b3) +#LIGHT SLEEPER +#draws first floor of WH +c1 = figure(plot_width=400, plot_height=400, tools=TOOLS,title="West Hall First Floor") +make_mapshape(c1) +#draws second floor of WH +c2 = figure(plot_width=400, plot_height=400, tools=TOOLS,title="West Hall Second Floor") +make_mapshape(c2) +#draws third floor of WH +c3 = figure(plot_width=400, plot_height=400, tools=TOOLS,title="West Hall Third Floor") +make_mapshape(c3) +#HALLWAY TIME +#draws first floor of WH +d1 = figure(plot_width=400, plot_height=400, tools=TOOLS,title="West Hall First Floor") +make_mapshape(d1) +#draws second floor of WH +d2 = figure(plot_width=400, plot_height=400, tools=TOOLS,title="West Hall Second Floor") +make_mapshape(d2) +#draws third floor of WH +d3 = figure(plot_width=400, plot_height=400, tools=TOOLS,title="West Hall Third Floor") +make_mapshape(d3) +#Pull data from csv file and create Room objects from it! +with open('WH_Freshmen.csv') as csvfile: + freshmen_data = csv.reader(csvfile, delimiter=',', quotechar='\"') + #roomList = [] + for row in freshmen_data: + roomA = Room() #initializes a new Room for each row in the csv data file + roomA.roomNum = row[0] + roomA.roomates = row[1] #not working for some reason? + roomA.gender = row[2] + roomA.bedtime = row[3] + roomA.lightsleep = row[4] + roomA.halltime = row[5] + + colors = roomA.findColors() + roomA.gendercolor = colors[0] + roomA.bedtimecolor = colors[1] + roomA.lightsleepcolor = colors[2] + roomA.halltimecolor = colors[3] + + coordinates = roomA.findCoordinates() + roomA.top = coordinates[0] + roomA.bottom = coordinates[1] + roomA.left = coordinates[2] + roomA.right = coordinates[3] + roomA.drawRoom() + + #roomList.append(roomA) #creates list of all Room objects + + +a = hplot(a1, a2, a3) +b = hplot(b1, b2, b3) +c = hplot(c1, c2, c3) +d = hplot(d1, d2, d3) +tabs = Tabs(tabs=[Panel(child=a, title="Gender"), Panel(child=b, title="Bedtime"), Panel(child=c, title="Heaviness of Sleep"), Panel(child=d, title="Time Spent In Hallway")]) + +# show the results +show(tabs) diff --git a/bokehlinetest.html b/bokehlinetest.html new file mode 100644 index 0000000..8cd2f29 --- /dev/null +++ b/bokehlinetest.html @@ -0,0 +1,30 @@ + + + + + + Bokeh Plot + + + + + + + + + + +
+ + + + \ No newline at end of file diff --git a/bokehtest.py b/bokehtest.py new file mode 100644 index 0000000..aae7652 --- /dev/null +++ b/bokehtest.py @@ -0,0 +1,23 @@ +from bokeh.models import BoxSelectTool, BoxZoomTool, LassoSelectTool +from bokeh.plotting import figure, output_file, show + +# output to static HTML file +output_file("bokehlinetest.html") + +p = figure(plot_width=400, plot_height=400) + +# add a circle renderer with a size, color, and alpha +selected_room = p.quad(top=[2],bottom=[1], left=[1], right=[2], color="navy", alpha=0.8) +unselected_room = p.quad(top=[2],bottom=[1], left=[1], right=[2], color="navy", alpha=0.2) + +p.segment(x0=[1, 1, 1, 6], y0=[1, 6, 1, 1], x1=[6, 6, 1, 6], + y1=[1, 6, 6, 6], color="#F4A582", line_width=3, legend="West Hall") + +p.select_one(BoxZoomTool).overlay.line_color = "olive" +p.select_one(BoxZoomTool).overlay.line_width = 8 +p.select_one(BoxZoomTool).overlay.line_dash = "solid" +p.select_one(BoxZoomTool).overlay.fill_color = None + + +# show the results +show(p) \ No newline at end of file diff --git a/bokehtest3.py b/bokehtest3.py new file mode 100644 index 0000000..1408ac6 --- /dev/null +++ b/bokehtest3.py @@ -0,0 +1,124 @@ +from bokeh.models import BoxSelectTool, BoxZoomTool, LassoSelectTool, HoverTool, Quad +from bokeh.plotting import figure, output_file, show, gridplot, ColumnDataSource +from bokeh.models.widgets import Dropdown, Panel, Tabs, CheckboxButtonGroup, RadioGroup +from bokeh.io import output_file, show, vform + +#PROJECT OVERVIEW: +#Create an interactive map of West Hall showing hallway culture via gender distribution, sleeping habit, etc. +#(If we hear back from STAR, we'll also have data on how people move from year to year, which will be awesome to implement) + +#PROGRESS: +#currently outputs to an html file which has 2 tabs - one for WH1 and one for WH2 +#rooms are currently blue squares, some with click and hover functionality, which is being modified and will be implemented in all once we figure out how to do it properly +#Also have buttons that are currently disfunctional but are planned to be able to display different color coordinations for each room. +#Will be initializing Room objects from a .csv file in this folder, but have not implemented yet. + + +# output to static HTML file +output_file("bokehlinetest.html") + +class Room(object): + def __init__(self, roomNum, roommates, gender, bedtime, top, bottom, left, right): + self.roomNum = roomNum + self.roommates = roommates + self.gender = gender + self.bedtime = bedtime + self.top = top + self.bottom = bottom + self.left = left + self.right = right + + def __str__(self): + return 'Room Number: %s; Current Inhabitants: %s; Gender: %s; Average Bedtime: %s' %(self.roomNum, self.roommates, self.gender, self.bedtime) + + +# This was our previous Way of setting data (now we'll be using a csv file and pulling data from there to initialize each Room object) +''' +#setting dictionary values for things on the first floor +source1 = ColumnDataSource( + data=dict( + roomates = ['Uma and Lauren', 'Margo and Nicole'], + gender = ['female', 'female'], + top=[2, 2], + bottom=[1, 1], + left=[1, 3], + right=[2, 4], + ) + ) +''' + +#setting what goes in the hover box (currently dysfunctional) +hover = HoverTool( + tooltips=[ + ("index", "@index"), + ("roomates", "@roomates"), + ("gender", "@gender") + ] + ) + +TOOLS = "box_zoom,box_select,resize,reset,hover,tap" + +p1 = figure(plot_width=400, plot_height=400, tools=TOOLS,title="West Hall First Floor") +rooms1 = p1.quad('top','bottom', 'left', 'right', + + #visual choices for when the room isn't selected, doesn't really work. + #also maybe not necessary to click to select rooms, but could + #be useful framework for changing color based on which button is selected + nonselection_fill_alpha=0.01, + nonselection_fill_color=None, + nonselection_line_color="firebrick", + nonselection_line_alpha=1.0, + + #visual choices for when the room is selected, actually works + selection_color="blue", + selection_fill_alpha=.5, + + #source for all of the room data + source=source1 + ) + +p1.segment(x0=[1, 1, 1, 6], y0=[1, 6, 1, 1], x1=[6, 6, 1, 6], + y1=[1, 6, 6, 6], color="#F4A582", line_width=3, legend="West Hall") +p1.select_one(BoxZoomTool).overlay.line_color = "olive" +p1.select_one(BoxZoomTool).overlay.line_width = 8 +p1.select_one(BoxZoomTool).overlay.line_dash = "solid" +p1.select_one(BoxZoomTool).overlay.fill_color = None +tab1 = Panel(child=p1, title="WH1") + +p2 = figure(plot_width=400, plot_height=400, tools=TOOLS,title="West Hall Second Floor") + +rooms2 = p2.quad(top=[2],bottom=[1], left=[1], right=[2], + + nonselection_fill_alpha=0.01, + nonselection_fill_color=None, + nonselection_line_color="firebrick", + nonselection_line_alpha=1.0, + + selection_color="blue", + selection_fill_alpha=.5) + +p2.segment(x0=[1, 1, 1, 6], y0=[1, 6, 1, 1], x1=[6, 6, 1, 6], + y1=[1, 6, 6, 6], color="#F4A582", line_width=3, legend="West Hall") + +p2.select_one(BoxZoomTool).overlay.line_color = "olive" +p2.select_one(BoxZoomTool).overlay.line_width = 8 +p2.select_one(BoxZoomTool).overlay.line_dash = "solid" +p2.select_one(BoxZoomTool).overlay.fill_color = None +tab2 = Panel(child=p2, title="WH2") + + +radio_group = RadioGroup( + labels=["Gender", "Bedtime", "Some other shit"], active=0) + +#dropdown_choices = [("Item 1", "item_1"), ("Item 2", "item_2"), ("Item 3", "item_3")] +#dropdown = Dropdown(label="Dropdown button", type="warning", menu=dropdown_choices) + + + +tabs = Tabs(tabs=[ tab1, tab2 ]) +layout = vform(dropdown, radio_group, tabs) + +# show the results +show(tabs) +show(layout) +#show(vform(checkbox_button_group)) \ No newline at end of file diff --git a/bokehtestLauren.py b/bokehtestLauren.py new file mode 100644 index 0000000..3518fbc --- /dev/null +++ b/bokehtestLauren.py @@ -0,0 +1,45 @@ +from bokeh.models import BoxSelectTool, BoxZoomTool, LassoSelectTool, HoverTool +from bokeh.plotting import figure, output_file, show, gridplot +from bokeh.models.widgets import Dropdown, Panel, Tabs, CheckboxButtonGroup +from bokeh.io import output_file, show, vform + +# output to static HTML file +output_file("bokehlinetest.html") +TOOLS = 'box_zoom,box_select,crosshair,resize,reset,hover' + +p1 = figure(plot_width=400, plot_height=400, tools=TOOLS,title="West Hall First Floor") +selected_room = p1.quad(top=[2],bottom=[1], left=[1], right=[2], color="navy", alpha=0.8) +unselected_room = p1.quad(top=[2],bottom=[1], left=[1], right=[2], color="navy", alpha=0.2) +p1.segment(x0=[1, 1, 1, 6], y0=[1, 6, 1, 1], x1=[6, 6, 1, 6], + y1=[1, 6, 6, 6], color="#F4A582", line_width=3, legend="West Hall") +p1.select_one(BoxZoomTool).overlay.line_color = "olive" +p1.select_one(BoxZoomTool).overlay.line_width = 8 +p1.select_one(BoxZoomTool).overlay.line_dash = "solid" +p1.select_one(BoxZoomTool).overlay.fill_color = None +tab1 = Panel(child=p1, title="WH1") + +p2 = figure(plot_width=400, plot_height=400, tools=TOOLS,title="West Hall Second Floor") +selected_room = p2.quad(top=[2],bottom=[1], left=[1], right=[2], color="navy", alpha=0.8) +unselected_room = p2.quad(top=[2],bottom=[1], left=[1], right=[2], color="navy", alpha=0.2) +p2.segment(x0=[1, 1, 1, 6], y0=[1, 6, 1, 1], x1=[6, 6, 1, 6], + y1=[1, 6, 6, 6], color="#F4A582", line_width=3, legend="West Hall") +p2.select_one(BoxZoomTool).overlay.line_color = "olive" +p2.select_one(BoxZoomTool).overlay.line_width = 8 +p2.select_one(BoxZoomTool).overlay.line_dash = "solid" +p2.select_one(BoxZoomTool).overlay.fill_color = None +tab2 = Panel(child=p2, title="WH2") + + +checkbox_button_group = CheckboxButtonGroup( + labels=["Gender", "Same Roommates", "Other Selectable Shit"], active=[0, 1]) +dropdown_choices = [("Item 1", "item_1"), ("Item 2", "item_2"), None, ("Item 3", "item_3")] +dropdown = Dropdown(label="Dropdown button", type="warning", menu=dropdown_choices) + + + +tabs = Tabs(tabs=[ tab1, tab2 ]) + +# show the results +show(tabs) +#show(vform(dropdown)) +#show(vform(checkbox_button_group)) \ No newline at end of file diff --git a/pygame_draw_state.py b/pygame_draw_state.py new file mode 100644 index 0000000..ace8eca --- /dev/null +++ b/pygame_draw_state.py @@ -0,0 +1,66 @@ +"""Sample code for `us_map.py`. + +Author: Oliver Steele +License: MIT + +Requirements: + + sudo pip install BeautifulSoup + sudo pip install matplotlib + sudo pip install svg.path +""" + +import pygame +import sys +import matplotlib.path +import us_map + +# Colors +WHITE = (255, 255, 255) +BLACK = (0, 0, 0) +BLUE = (0, 0, 255) +GREEN = (0, 255, 0) +GRAY = (127, 127, 127) +LIGHT_GRAY = (191, 191, 191) + +STATE = 'CO' + +width, height = 640, 480 + +pygame.init() +screen = pygame.display.set_mode((width, height)) +screen.fill(WHITE) + + +def point_in_polygon(pt, polygon): + """Returns True iff `pt` is inside `polygon`. + `polygon` is a list of tuples `(x, y)`.""" + + return matplotlib.path.Path(polygon).contains_point(pt) + +# Draw the polygons for the state. +for polygon in us_map.states[STATE]: + # `polygon` points are tuples `(float, float)`. PyGame requires `(int, int)`. + points = [(int(x), int(y)) for x, y in polygon] + # Draw the interior + pygame.draw.polygon(screen, BLUE, points) + # Draw the boundary + pygame.draw.polygon(screen, BLACK, points, 1) + +pygame.display.flip() + +last_mouse_in_state = False + +while True: + if any(event.type == pygame.QUIT for event in pygame.event.get()): + sys.exit() + + # Is the mouse inside the state? + mouse_in_state = any(point_in_polygon(pygame.mouse.get_pos(), polygon) for polygon in us_map.states[STATE]) + # Only print a message if the mouse moved from the inside to the outside, or vice versa + if mouse_in_state != last_mouse_in_state: + last_mouse_in_state = mouse_in_state + if mouse_in_state: + print 'mouse in state' + else: + print 'mouse not in state' diff --git a/us_map.py b/us_map.py new file mode 100644 index 0000000..ee16b00 --- /dev/null +++ b/us_map.py @@ -0,0 +1,76 @@ +"""Exports a dict `states` that maps state codes to lists of polygons. + +Author: Oliver Steele +License: MIT + +Requirements: + + sudo pip install BeautifulSoup + sudo pip install svg.path +""" + +from BeautifulSoup import BeautifulSoup +from collections import OrderedDict +from svg.path import parse_path + +states = None +"""A `dict` of state abbreviations (e.g. `"MA"`) to lists of polygons. Each polygon is a list of points. +Each point is a tuple of floats `(x, y)`.""" + +props = ['start', 'control', 'control1', 'control2', 'end'] + + +def get_segment_control_points(segment): + """Given an `svg.path` segment, return its list of control points. + Each control point is a complex number.""" + + # segment_type = segment.__class__.__name__ + # assert segment_type in ['Line', 'CubicBezier'], segment_type + return [getattr(segment, prop) for prop in props if hasattr(segment, prop)] + + +def path_to_points(path): + """Given an `svg.path` Path, return its list of control points. + Each control point is a pair of float `(x, y)`.""" + + return [(pt.real, pt.imag) + for segment in path + for pt in get_segment_control_points(segment)] + + +def initialize(svg_filename='Blank_US_Map.svg'): + """Initialize the `states` global variable.""" + + with open(svg_filename, 'r') as svg: + soup = BeautifulSoup(svg.read(), selfClosingTags=['defs']) + paths = soup.findAll('path') + + global states + states = {} + for p in paths: + state_name = p.get('id', None) + path_string = p.get('d', None) + if not state_name or not path_string: + continue + # `svg.path` treats the Move command as though it were Line. + # Split the path data, in order to collect one Path per contour. + path_strings = [s for s in path_string.split('m') if s] + polygons = [] + path_prefix = 'm' + for path_string in path_strings: + if path_string[0] not in 'M': + path_string = path_prefix + path_string + path = parse_path(path_string) + polygons.append(path_to_points(path)) + end_pt = path[-1].end + end_pt = path[0].start + path_prefix = 'M %f,%f m' % (end_pt.real, end_pt.imag) + states[state_name] = polygons + + states = OrderedDict(sorted(states.items())) + +initialize() + +if __name__ == '__main__': + print states['CA'] +