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