##// END OF EJS Templates
Fix extra ) syntax error
David Österberg -
Show More
@@ -1,489 +1,489 b''
1 1 """Various display related classes.
2 2
3 3 Authors : MinRK, gregcaporaso, dannystaple
4 4 """
5 5 from os.path import exists, isfile, splitext, abspath, join, isdir
6 6 from os import walk, sep
7 7
8 8 from IPython.core.display import DisplayObject
9 9
10 10
11 11 class Audio(DisplayObject):
12 12 """Create an audio object.
13 13
14 14 When this object is returned by an input cell or passed to the
15 15 display function, it will result in Audio controls being displayed
16 16 in the frontend (only works in the notebook).
17 17
18 18 Parameters
19 19 ----------
20 20 data : numpy array, unicode, str or bytes
21 21 Can be a
22 22 * Numpy array containing the desired waveform,
23 23 * String containing the filename
24 24 * Bytestring containing raw PCM data or
25 25 * URL pointing to a file on the web.
26 26
27 27 If the array option is used the waveform will be normalized.
28 28
29 29 If a filename or url is used the format support will be browser
30 30 dependent.
31 31 url : unicode
32 32 A URL to download the data from.
33 33 filename : unicode
34 34 Path to a local file to load the data from.
35 35 embed : boolean
36 36 Should the image data be embedded using a data URI (True) or should
37 37 the original source be referenced. Set this to True if you want the
38 38 audio to playable later with no internet connection in the notebook.
39 39
40 40 Default is `True`, unless the keyword argument `url` is set, then
41 41 default value is `False`.
42 42 rate : integer
43 43 The sampling rate of the raw data.
44 44 Only required when data parameter is being used as an array
45 45 autoplay : bool
46 46 Set to True if the audio should immediately start playing.
47 47 Default is `False`.
48 48
49 49 Examples
50 50 --------
51 51
52 52 # Generate a sound
53 53 import numpy as np
54 54 framerate = 44100
55 55 t = np.linspace(0,5,framerate*5)
56 56 data = np.sin(2*np.pi*440*np.sin(10*t**2))
57 57 Audio(data,rate=framerate)
58 58
59 59 Audio("http://www.nch.com.au/acm/8k16bitpcm.wav")
60 60 Audio(url="http://media.bradsucks.net/albums/ooi-128/01_-_Brad_Sucks_-_Dropping_out_of_School.mp3")
61 61 Audio(url="http://www.w3schools.com/html/horse.ogg", embed=True)
62 62
63 63 Audio('/path/to/sound.wav')
64 64 Audio(filename='/path/to/sound.ogg')
65 65
66 66 Audio(b'RAW_WAV_DATA..)
67 67 Audio(data=b'RAW_WAV_DATA..)
68 68
69 69 """
70 70
71 71 def __init__(self, data=None, filename=None, url=None, embed=None, rate=None, autoplay=False):
72 72 if filename is None and url is None and data is None:
73 73 raise ValueError("No image data found. Expecting filename, url, or data.")
74 74 if embed is False and url is None:
75 75 raise ValueError("No url found. Expecting url when embed=False")
76 76
77 77 if url is not None and embed is not True:
78 78 self.embed = False
79 79 else:
80 80 self.embed = True
81 81 self.autoplay = autoplay
82 82 super(Audio, self).__init__(data=data, url=url, filename=filename)
83 83
84 84 if self.data is not None and not isinstance(self.data, bytes):
85 85 self.data = self._make_wav(data,rate)
86 86
87 87 def reload(self):
88 88 """Reload the raw data from file or URL."""
89 89 import mimetypes
90 90 if self.embed:
91 91 super(Audio, self).reload()
92 92
93 93 if self.filename is not None:
94 94 self.mimetype = mimetypes.guess_type(self.filename)[0]
95 95 elif self.url is not None:
96 96 self.mimetype = mimetypes.guess_type(self.url)[0]
97 97 else:
98 98 self.mimetype = "audio/wav"
99 99
100 100
101 101 def _make_wav(self,data,rate):
102 102 """ Transform a numpy array to a PCM bytestring """
103 103 import struct
104 104 from io import BytesIO
105 105 import wave
106 106 maxabsvalue = max(map(abs,data))
107 107 scaled = map(lambda x: int(x/maxabsvalue*32767), data)
108 108 fp = BytesIO()
109 109 waveobj = wave.open(fp,mode='wb')
110 110 waveobj.setnchannels(1)
111 111 waveobj.setframerate(rate)
112 112 waveobj.setsampwidth(2)
113 113 waveobj.setcomptype('NONE','NONE')
114 114 waveobj.writeframes(b''.join([struct.pack('<h',x) for x in scaled]))
115 115 val = fp.getvalue()
116 116 waveobj.close()
117 117 return val
118 118
119 119 def _data_and_metadata(self):
120 120 """shortcut for returning metadata with url information, if defined"""
121 121 md = {}
122 122 if self.url:
123 123 md['url'] = self.url
124 124 if md:
125 125 return self.data, md
126 126 else:
127 127 return self.data
128 128
129 129 def _repr_html_(self):
130 130 src = """
131 131 <audio controls="controls" {autoplay}>
132 132 <source src="{src}" type="{type}" />
133 133 Your browser does not support the audio element.
134 134 </audio>
135 135 """
136 136 return src.format(src=self.src_attr(),type=self.mimetype, autoplay=self.autoplay_attr())
137 137
138 138 def src_attr(self):
139 139 import base64
140 140 if self.embed and (self.data is not None):
141 data = base64=base64.b64encode(self.data).decode('ascii'))
141 data = base64=base64.b64encode(self.data).decode('ascii')
142 142 return """data:{type};base64,{base64}""".format(type=self.mimetype,
143 143 base64=data)
144 144 elif self.url is not None:
145 145 return self.url
146 146 else:
147 147 return ""
148 148
149 149 def autoplay_attr(self):
150 150 if(self.autoplay):
151 151 return 'autoplay="autoplay"'
152 152 else:
153 153 return ''
154 154
155 155 class IFrame(object):
156 156 """
157 157 Generic class to embed an iframe in an IPython notebook
158 158 """
159 159
160 160 iframe = """
161 161 <iframe
162 162 width="{width}"
163 163 height={height}"
164 164 src="{src}{params}"
165 165 frameborder="0"
166 166 allowfullscreen
167 167 ></iframe>
168 168 """
169 169
170 170 def __init__(self, src, width, height, **kwargs):
171 171 self.src = src
172 172 self.width = width
173 173 self.height = height
174 174 self.params = kwargs
175 175
176 176 def _repr_html_(self):
177 177 """return the embed iframe"""
178 178 if self.params:
179 179 from urllib import urlencode
180 180 params = "?" + urlencode(self.params)
181 181 else:
182 182 params = ""
183 183 return self.iframe.format(src=self.src,
184 184 width=self.width,
185 185 height=self.height,
186 186 params=params)
187 187
188 188 class YouTubeVideo(IFrame):
189 189 """Class for embedding a YouTube Video in an IPython session, based on its video id.
190 190
191 191 e.g. to embed the video on this page:
192 192
193 193 http://www.youtube.com/watch?v=foo
194 194
195 195 you would do:
196 196
197 197 vid = YouTubeVideo("foo")
198 198 display(vid)
199 199
200 200 To start from 30 seconds:
201 201
202 202 vid = YouTubeVideo("abc", start=30)
203 203 display(vid)
204 204
205 205 To calculate seconds from time as hours, minutes, seconds use:
206 206 start=int(timedelta(hours=1, minutes=46, seconds=40).total_seconds())
207 207
208 208 Other parameters can be provided as documented at
209 209 https://developers.google.com/youtube/player_parameters#parameter-subheader
210 210 """
211 211
212 212 def __init__(self, id, width=400, height=300, **kwargs):
213 213 src = "http://www.youtube.com/embed/{0}".format(id)
214 214 super(YouTubeVideo, self).__init__(src, width, height, **kwargs)
215 215
216 216 class VimeoVideo(IFrame):
217 217 """
218 218 Class for embedding a Vimeo video in an IPython session, based on its video id.
219 219 """
220 220
221 221 def __init__(self, id, width=400, height=300, **kwargs):
222 222 src="http://player.vimeo.com/video/{0}".format(id)
223 223 super(VimeoVideo, self).__init__(src, width, height, **kwargs)
224 224
225 225 class ScribdDocument(IFrame):
226 226 """
227 227 Class for embedding a Scribd document in an IPython session
228 228
229 229 Use the start_page params to specify a starting point in the document
230 230 Use the view_mode params to specify display type one off scroll | slideshow | book
231 231
232 232 e.g to Display Wes' foundational paper about PANDAS in book mode from page 3
233 233
234 234 ScribdDocument(71048089, width=800, height=400, start_page=3, view_mode="book")
235 235 """
236 236
237 237 def __init__(self, id, width=400, height=300, **kwargs):
238 238 src="http://www.scribd.com/embeds/{0}/content".format(id)
239 239 super(ScribdDocument, self).__init__(src, width, height, **kwargs)
240 240
241 241 class FileLink(object):
242 242 """Class for embedding a local file link in an IPython session, based on path
243 243
244 244 e.g. to embed a link that was generated in the IPython notebook as my/data.txt
245 245
246 246 you would do::
247 247
248 248 local_file = FileLink("my/data.txt")
249 249 display(local_file)
250 250
251 251 or in the HTML notebook, just::
252 252
253 253 FileLink("my/data.txt")
254 254 """
255 255
256 256 html_link_str = "<a href='%s' target='_blank'>%s</a>"
257 257
258 258 def __init__(self,
259 259 path,
260 260 url_prefix='files/',
261 261 result_html_prefix='',
262 262 result_html_suffix='<br>'):
263 263 """
264 264 Parameters
265 265 ----------
266 266 path : str
267 267 path to the file or directory that should be formatted
268 268 directory_prefix : str
269 269 prefix to be prepended to all files to form a working link [default:
270 270 'files']
271 271 result_html_prefix : str
272 272 text to append to beginning to link [default: none]
273 273 result_html_suffix : str
274 274 text to append at the end of link [default: '<br>']
275 275 """
276 276 if isdir(path):
277 277 raise ValueError,\
278 278 ("Cannot display a directory using FileLink. "
279 279 "Use FileLinks to display '%s'." % path)
280 280 self.path = path
281 281 self.url_prefix = url_prefix
282 282 self.result_html_prefix = result_html_prefix
283 283 self.result_html_suffix = result_html_suffix
284 284
285 285 def _format_path(self):
286 286 fp = ''.join([self.url_prefix,self.path])
287 287 return ''.join([self.result_html_prefix,
288 288 self.html_link_str % (fp, self.path),
289 289 self.result_html_suffix])
290 290
291 291 def _repr_html_(self):
292 292 """return html link to file
293 293 """
294 294 if not exists(self.path):
295 295 return ("Path (<tt>%s</tt>) doesn't exist. "
296 296 "It may still be in the process of "
297 297 "being generated, or you may have the "
298 298 "incorrect path." % self.path)
299 299
300 300 return self._format_path()
301 301
302 302 def __repr__(self):
303 303 """return absolute path to file
304 304 """
305 305 return abspath(self.path)
306 306
307 307 class FileLinks(FileLink):
308 308 """Class for embedding local file links in an IPython session, based on path
309 309
310 310 e.g. to embed links to files that were generated in the IPython notebook under my/data
311 311
312 312 you would do:
313 313
314 314 local_files = FileLinks("my/data")
315 315 display(local_files)
316 316
317 317 or in the HTML notebook, just
318 318
319 319 FileLinks("my/data")
320 320
321 321 """
322 322 def __init__(self,
323 323 path,
324 324 url_prefix='files/',
325 325 included_suffixes=None,
326 326 result_html_prefix='',
327 327 result_html_suffix='<br>',
328 328 notebook_display_formatter=None,
329 329 terminal_display_formatter=None):
330 330 """
331 331 included_suffixes : list of filename suffixes to include when
332 332 formatting output [default: include all files]
333 333
334 334 See the FileLink (baseclass of LocalDirectory) docstring for
335 335 information on additional parameters.
336 336
337 337 notebook_display_formatter : func used to format links for display
338 338 in the notebook. See discussion of formatter function below.
339 339
340 340 terminal_display_formatter : func used to format links for display
341 341 in the terminal. See discussion of formatter function below.
342 342
343 343
344 344 Passing custom formatter functions
345 345 ----------------------------------
346 346 Formatter functions must be of the form:
347 347 f(dirname, fnames, included_suffixes)
348 348 dirname : the name of a directory (a string),
349 349 fnames : a list of the files in that directory
350 350 included_suffixes : a list of the file suffixes that should be
351 351 included in the output (passing None means
352 352 to include all suffixes in the output in
353 353 the built-in formatters)
354 354
355 355 returns a list of lines that should will be print in the
356 356 notebook (if passing notebook_display_formatter) or the terminal
357 357 (if passing terminal_display_formatter). This function is iterated
358 358 over for each directory in self.path. Default formatters are in
359 359 place, can be passed here to support alternative formatting.
360 360
361 361 """
362 362 if isfile(path):
363 363 raise ValueError,\
364 364 ("Cannot display a file using FileLinks. "
365 365 "Use FileLink to display '%s'." % path)
366 366 self.included_suffixes = included_suffixes
367 367 # remove trailing slashs for more consistent output formatting
368 368 path = path.rstrip('/')
369 369
370 370 self.path = path
371 371 self.url_prefix = url_prefix
372 372 self.result_html_prefix = result_html_prefix
373 373 self.result_html_suffix = result_html_suffix
374 374
375 375 self.notebook_display_formatter = \
376 376 notebook_display_formatter or self._get_notebook_display_formatter()
377 377 self.terminal_display_formatter = \
378 378 terminal_display_formatter or self._get_terminal_display_formatter()
379 379
380 380 def _get_display_formatter(self,
381 381 dirname_output_format,
382 382 fname_output_format,
383 383 fp_format,
384 384 fp_cleaner=None):
385 385 """ generate built-in formatter function
386 386
387 387 this is used to define both the notebook and terminal built-in
388 388 formatters as they only differ by some wrapper text for each entry
389 389
390 390 dirname_output_format: string to use for formatting directory
391 391 names, dirname will be substituted for a single "%s" which
392 392 must appear in this string
393 393 fname_output_format: string to use for formatting file names,
394 394 if a single "%s" appears in the string, fname will be substituted
395 395 if two "%s" appear in the string, the path to fname will be
396 396 substituted for the first and fname will be substituted for the
397 397 second
398 398 fp_format: string to use for formatting filepaths, must contain
399 399 exactly two "%s" and the dirname will be subsituted for the first
400 400 and fname will be substituted for the second
401 401 """
402 402 def f(dirname, fnames, included_suffixes=None):
403 403 result = []
404 404 # begin by figuring out which filenames, if any,
405 405 # are going to be displayed
406 406 display_fnames = []
407 407 for fname in fnames:
408 408 if (isfile(join(dirname,fname)) and
409 409 (included_suffixes == None or
410 410 splitext(fname)[1] in included_suffixes)):
411 411 display_fnames.append(fname)
412 412
413 413 if len(display_fnames) == 0:
414 414 # if there are no filenames to display, don't print anything
415 415 # (not even the directory name)
416 416 pass
417 417 else:
418 418 # otherwise print the formatted directory name followed by
419 419 # the formatted filenames
420 420 dirname_output_line = dirname_output_format % dirname
421 421 result.append(dirname_output_line)
422 422 for fname in display_fnames:
423 423 fp = fp_format % (dirname,fname)
424 424 if fp_cleaner is not None:
425 425 fp = fp_cleaner(fp)
426 426 try:
427 427 # output can include both a filepath and a filename...
428 428 fname_output_line = fname_output_format % (fp, fname)
429 429 except TypeError:
430 430 # ... or just a single filepath
431 431 fname_output_line = fname_output_format % fname
432 432 result.append(fname_output_line)
433 433 return result
434 434 return f
435 435
436 436 def _get_notebook_display_formatter(self,
437 437 spacer="&nbsp;&nbsp;"):
438 438 """ generate function to use for notebook formatting
439 439 """
440 440 dirname_output_format = \
441 441 self.result_html_prefix + "%s/" + self.result_html_suffix
442 442 fname_output_format = \
443 443 self.result_html_prefix + spacer + self.html_link_str + self.result_html_suffix
444 444 fp_format = self.url_prefix + '%s/%s'
445 445 if sep == "\\":
446 446 # Working on a platform where the path separator is "\", so
447 447 # must convert these to "/" for generating a URI
448 448 def fp_cleaner(fp):
449 449 # Replace all occurences of backslash ("\") with a forward
450 450 # slash ("/") - this is necessary on windows when a path is
451 451 # provided as input, but we must link to a URI
452 452 return fp.replace('\\','/')
453 453 else:
454 454 fp_cleaner = None
455 455
456 456 return self._get_display_formatter(dirname_output_format,
457 457 fname_output_format,
458 458 fp_format,
459 459 fp_cleaner)
460 460
461 461 def _get_terminal_display_formatter(self,
462 462 spacer=" "):
463 463 """ generate function to use for terminal formatting
464 464 """
465 465 dirname_output_format = "%s/"
466 466 fname_output_format = spacer + "%s"
467 467 fp_format = '%s/%s'
468 468
469 469 return self._get_display_formatter(dirname_output_format,
470 470 fname_output_format,
471 471 fp_format)
472 472
473 473 def _format_path(self):
474 474 result_lines = []
475 475 walked_dir = list(walk(self.path))
476 476 walked_dir.sort()
477 477 for dirname, subdirs, fnames in walked_dir:
478 478 result_lines += self.notebook_display_formatter(dirname, fnames, self.included_suffixes)
479 479 return '\n'.join(result_lines)
480 480
481 481 def __repr__(self):
482 482 """return newline-separated absolute paths
483 483 """
484 484 result_lines = []
485 485 walked_dir = list(walk(self.path))
486 486 walked_dir.sort()
487 487 for dirname, subdirs, fnames in walked_dir:
488 488 result_lines += self.terminal_display_formatter(dirname, fnames, self.included_suffixes)
489 489 return '\n'.join(result_lines)
General Comments 0
You need to be logged in to leave comments. Login now