1 00:00:00,000 --> 00:00:01,109 [No audio] 2 00:00:01,110 --> 00:00:03,390 Great, we have a graph of visualizing 3 00:00:03,390 --> 00:00:05,730 the time intervals. So when the object 4 00:00:05,730 --> 00:00:08,460 entered the video frame. Now let's go 5 00:00:08,460 --> 00:00:11,670 ahead and modify our code so that we add 6 00:00:11,700 --> 00:00:13,950 a window. So a window will popup here 7 00:00:13,950 --> 00:00:17,370 when the user hovers the mouse over this 8 00:00:17,564 --> 00:00:23,174 quadrant. Let's do that. And the Bokeh 9 00:00:23,190 --> 00:00:24,930 tool to implement the hover 10 00:00:24,930 --> 00:00:28,230 functionality is called the hover tool. 11 00:00:29,400 --> 00:00:32,700 And that is accessed from the lower level 12 00:00:32,700 --> 00:00:36,746 interface called models. So bokeh.models. 13 00:00:38,059 --> 00:00:41,919 So you want to import the HoverTool. 14 00:00:42,989 --> 00:00:44,370 Let's now see how we're going to 15 00:00:44,370 --> 00:00:47,790 use this inside our script. And 16 00:00:47,790 --> 00:00:49,830 basically, this is a method that expects 17 00:00:49,830 --> 00:00:53,100 from you some arrays with data, so that 18 00:00:53,100 --> 00:00:55,740 the HoverTool method will display them 19 00:00:55,740 --> 00:00:57,390 when the user hovers the mouse over 20 00:00:57,390 --> 00:01:00,960 these quadrant. So if a cursor is on 21 00:01:00,990 --> 00:01:03,570 this particular quadrant, let's say the 22 00:01:03,570 --> 00:01:05,790 data for that quadrant will be displayed 23 00:01:06,270 --> 00:01:11,220 on the popup window. So what you want to 24 00:01:11,220 --> 00:01:15,089 do is, once you have created your figure, 25 00:01:15,090 --> 00:01:17,923 [No audio] 26 00:01:17,925 --> 00:01:19,913 you want to create a hover object, 27 00:01:20,155 --> 00:01:22,507 which will be equal to the HoverTool 28 00:01:22,508 --> 00:01:26,863 [Author typing] 29 00:01:26,864 --> 00:01:30,180 which has a tooltips parameter 30 00:01:30,180 --> 00:01:34,080 there. And this will get us argument 31 00:01:35,010 --> 00:01:39,600 list of tuples. And in every tuple, you 32 00:01:39,600 --> 00:01:42,810 want to specify the lines of the popup 33 00:01:42,810 --> 00:01:45,150 window. So let's say in the first line 34 00:01:45,150 --> 00:01:48,330 of your popup window, you would want to have 35 00:01:49,170 --> 00:01:51,960 a Start string. And beside that Start 36 00:01:51,960 --> 00:01:54,720 string, you want to have the array with 37 00:01:54,720 --> 00:01:57,450 your data. This has this special 38 00:01:57,450 --> 00:02:00,390 decorator here. So in our case, that 39 00:02:00,390 --> 00:02:02,280 would be the start column from the data 40 00:02:02,280 --> 00:02:06,210 frame. So we want the start time and 41 00:02:06,210 --> 00:02:08,970 end time as well. So End for the 42 00:02:08,970 --> 00:02:14,490 string, and for the name of the 43 00:02:14,490 --> 00:02:19,140 column. So that should do it almost. But 44 00:02:19,140 --> 00:02:21,421 we need to add this tool using the 45 00:02:21,423 --> 00:02:25,800 add_tools method. So the hover objects do we 46 00:02:25,800 --> 00:02:28,680 need to add it to the tool menus, so 47 00:02:28,680 --> 00:02:32,790 this should be a dot. That's it. And 48 00:02:32,790 --> 00:02:34,500 we're going to have to add more here 49 00:02:34,500 --> 00:02:38,970 but, let's see what we get this far. So 50 00:02:39,000 --> 00:02:41,086 python plotting.py. 51 00:02:41,087 --> 00:02:45,027 [No audio] 52 00:02:45,028 --> 00:02:50,356 Here some object, another one, and another one and quit. 53 00:02:50,357 --> 00:02:53,857 [No audio] 54 00:02:53,858 --> 00:02:57,330 So yeah, here is the graph. We're 55 00:02:57,330 --> 00:03:02,010 almost there. But not yet. So as 56 00:03:02,010 --> 00:03:04,590 you see, for some reason, Python is 57 00:03:04,740 --> 00:03:07,380 having trouble fetching the values of 58 00:03:07,380 --> 00:03:10,590 this Start and End column. And you also 59 00:03:10,590 --> 00:03:12,990 notice that we have two columns for each 60 00:03:12,990 --> 00:03:16,350 of these rows here. So the first thing 61 00:03:16,410 --> 00:03:18,090 you want to do is remove this column, 62 00:03:18,090 --> 00:03:20,130 you don't leave this because Bokeh is 63 00:03:20,130 --> 00:03:24,420 adding it by default. So that sees and 64 00:03:24,420 --> 00:03:26,550 also solve the other problem, the main 65 00:03:26,550 --> 00:03:30,720 problem of a question marks, it's by 66 00:03:30,720 --> 00:03:34,320 adding the ColumnDataSource methods 67 00:03:34,321 --> 00:03:39,178 [Author typing] 68 00:03:39,180 --> 00:03:41,460 which comes from the bokeh.models 69 00:03:41,490 --> 00:03:45,466 low level interface. So ColumnDataSource 70 00:03:45,468 --> 00:03:48,420 is a standardized way to provide 71 00:03:48,420 --> 00:03:51,630 data to a Bokeh plot. So if you've got 72 00:03:51,630 --> 00:03:54,060 data frames, list or other objects, 73 00:03:55,290 --> 00:03:58,080 some for some functions in Bokeh, you 74 00:03:58,080 --> 00:04:00,716 need to convert them to a ColumnDataSource 75 00:04:00,718 --> 00:04:02,820 object, which actually is very 76 00:04:02,820 --> 00:04:07,440 easy. And let me do it here. So we grab 77 00:04:07,440 --> 00:04:10,380 the data frame here. And then let's say 78 00:04:10,380 --> 00:04:14,580 ColumnDataSource cds, that would be 79 00:04:14,580 --> 00:04:17,430 equal to ColumnDataSource. So the 80 00:04:17,430 --> 00:04:20,040 methods and the data you want pass to 81 00:04:20,040 --> 00:04:22,020 it. So we have a data frame this case. 82 00:04:22,470 --> 00:04:25,740 And then once you do that, you need to 83 00:04:25,770 --> 00:04:29,610 adjust here, not the figure object, 84 00:04:29,640 --> 00:04:32,160 because we are not passing any data 85 00:04:32,160 --> 00:04:34,770 here. We're just constructing the 86 00:04:34,830 --> 00:04:37,980 environment for the plot. But you need 87 00:04:38,010 --> 00:04:41,790 to modify the quad method. So 88 00:04:41,790 --> 00:04:44,910 specifically, you want to pass source 89 00:04:44,910 --> 00:04:48,180 parameter here, which should be equal to 90 00:04:48,210 --> 00:04:51,780 the ColumnDataSource object. So cds in 91 00:04:51,780 --> 00:04:54,090 our case, this one here. So you're 92 00:04:54,090 --> 00:04:56,160 telling Bokeh to use this data and 93 00:04:56,160 --> 00:04:59,220 then you don't need to point to the data 94 00:04:59,220 --> 00:05:05,670 frame. So just enter the names of your 95 00:05:05,700 --> 00:05:09,808 columns there. So let's see what we have this time. 96 00:05:09,809 --> 00:05:14,259 [No audio] 97 00:05:14,261 --> 00:05:17,760 Object, another one, quit. 98 00:05:17,761 --> 00:05:20,938 [No audio] 99 00:05:20,940 --> 00:05:25,980 Here's a graph. And yeah, almost there. 100 00:05:26,370 --> 00:05:29,520 But the problem is, this time we're not 101 00:05:29,520 --> 00:05:31,740 getting the dates in the correct format. 102 00:05:33,060 --> 00:05:34,920 The reason to that is the HoverTool 103 00:05:34,920 --> 00:05:39,270 method. So here we are here. The 104 00:05:39,270 --> 00:05:41,340 HoverTool method is not being able to 105 00:05:41,340 --> 00:05:45,060 fetch datetimes datatypes. But that's 106 00:05:45,060 --> 00:05:47,100 nothing to worry about because what we 107 00:05:47,100 --> 00:05:50,005 can do is, so we can cover the datetimes 108 00:05:50,302 --> 00:05:54,023 toStrings in the DataFrame. So before, 109 00:05:54,886 --> 00:05:56,400 before we pass the DataFrame to 110 00:05:56,400 --> 00:06:00,030 the ColumnDataSource object method, we 111 00:06:00,030 --> 00:06:02,610 cover those start and the end columns 112 00:06:03,000 --> 00:06:05,460 toString datatypes. So you will 113 00:06:05,460 --> 00:06:07,866 already know how to work with datetimes. 114 00:06:08,776 --> 00:06:10,950 So in this case, we will do some 115 00:06:11,070 --> 00:06:15,300 datetime formatting. So what we 116 00:06:15,300 --> 00:06:19,080 could do is create another, so a new 117 00:06:19,080 --> 00:06:23,310 column, let's say Start_string, so the 118 00:06:23,310 --> 00:06:25,200 string version of the Start column, 119 00:06:25,920 --> 00:06:28,260 which should be equal to the existing 120 00:06:28,320 --> 00:06:35,070 Start column, .d, .dt which enables 121 00:06:35,070 --> 00:06:39,030 you to do datetime formatting, and strftime. 122 00:06:40,590 --> 00:06:43,380 Here is now how you define your data to 123 00:06:43,380 --> 00:06:46,290 be displayed. So we would want to 124 00:06:46,290 --> 00:06:49,047 display the year first, and then the month 125 00:06:49,531 --> 00:06:53,610 a dash, and the day after that. And maybe 126 00:06:53,610 --> 00:07:00,281 a space there and then hour, minutes, and seconds. 127 00:07:00,282 --> 00:07:02,735 [No audio] 128 00:07:02,737 --> 00:07:04,680 And the same goes for the End 129 00:07:05,310 --> 00:07:12,030 column. So End_string, and here and same 130 00:07:12,030 --> 00:07:15,450 here. And as you can assume now, we 131 00:07:15,450 --> 00:07:17,850 need to reflect those changes in here. 132 00:07:17,850 --> 00:07:20,640 So these should be Start_string and 133 00:07:20,640 --> 00:07:23,910 this should be the End_string. So we are 134 00:07:23,910 --> 00:07:27,852 displaying these strings now to the 135 00:07:27,854 --> 00:07:32,234 popup window. And let's see how this goes this time. 136 00:07:32,235 --> 00:07:37,273 [No audio] 137 00:07:37,274 --> 00:07:41,241 First object passes there second, 138 00:07:42,666 --> 00:07:46,274 and last, and one more quit. 139 00:07:46,275 --> 00:07:48,776 [No audio] 140 00:07:48,778 --> 00:07:54,540 And we have a problem here, I suppose. If I 141 00:07:54,540 --> 00:07:57,570 didn't change the values in here, so I 142 00:07:57,570 --> 00:08:00,680 did completely the wrong thing. I shouldn't 143 00:08:00,682 --> 00:08:03,240 have changed the dates in this 144 00:08:03,900 --> 00:08:06,360 quadrant object because these series 145 00:08:06,390 --> 00:08:09,300 datetimes, because we have defined the 146 00:08:09,300 --> 00:08:11,433 axis datetime here. So these 147 00:08:11,435 --> 00:08:14,550 express datetimes. So here's should be 148 00:08:14,550 --> 00:08:16,830 the Start, the original Start column and 149 00:08:16,830 --> 00:08:20,100 here the End column. So by mistake, I 150 00:08:20,107 --> 00:08:25,047 put those values in there. So Start_string 151 00:08:25,048 --> 00:08:30,831 in here, End_string in here. So 152 00:08:30,840 --> 00:08:33,090 that should do it this time. Let's 153 00:08:33,104 --> 00:08:36,976 double check. Everything looks good. 154 00:08:38,234 --> 00:08:39,280 And let's see. 155 00:08:39,281 --> 00:08:42,439 [No audio] 156 00:08:42,441 --> 00:08:44,331 Here, we go. 157 00:08:44,332 --> 00:08:49,588 [No audio] 158 00:08:49,590 --> 00:08:52,590 Yeah, we were able to grab the data, or 159 00:08:52,590 --> 00:08:56,790 let's see. Yeah, this looks good. So now 160 00:08:56,790 --> 00:08:59,760 I believe this graph is quite readable. 161 00:09:00,150 --> 00:09:02,730 And I believe you were able to pull out 162 00:09:02,730 --> 00:09:04,620 some information, although this graph, 163 00:09:05,040 --> 00:09:07,350 so you can see how long an object stayed 164 00:09:07,800 --> 00:09:11,910 in the video frame and when it started, 165 00:09:12,270 --> 00:09:15,180 and when it exiting the frame. And I hope 166 00:09:15,180 --> 00:09:18,150 you find this useful sometimes. As I 167 00:09:18,150 --> 00:09:20,730 already said, you can use a Raspberry Pi 168 00:09:20,730 --> 00:09:24,300 Server. So we just a small computer and 169 00:09:24,630 --> 00:09:27,030 host this application in your in that 170 00:09:27,030 --> 00:09:29,700 server. And of course you can build and 171 00:09:29,700 --> 00:09:31,440 of course you can mount a camera in 172 00:09:31,440 --> 00:09:33,660 their server and have it capture some 173 00:09:33,660 --> 00:09:36,300 video for your needs. But most 174 00:09:36,300 --> 00:09:39,510 importantly, I hope you learned from 175 00:09:39,510 --> 00:09:41,700 this practice activity. And I know that 176 00:09:41,700 --> 00:09:44,490 was quite a lot to consume. And I'll 177 00:09:44,490 --> 00:09:46,980 talk to you later on in the next 178 00:09:46,980 --> 00:09:48,060 lectures. See you. 179 00:09:48,061 --> 00:09:49,504 [No audio]