#!/usr/bin/env python # coding: utf-8 # # Vispy # Vispy 0.3 (this two demos) is about building the low-level infrastructure # # see this tutorial about [opengl and vispy gloo module](http://www.labri.fr/perso/nrougier/teaching/opengl/) # # Vispy 0.4 starts to bring higher level structures # In[2]: # Vispy demo: ray traycing # http://vispy.org/examples/demo/gloo/raytracing.html from math import cos from vispy import app, gloo vertex = """ #version 120 attribute vec2 a_position; varying vec2 v_position; void main() { gl_Position = vec4(a_position, 0.0, 1.0); v_position = a_position; } """ fragment = """ #version 120 const float M_PI = 3.14159265358979323846; const float INFINITY = 1000000000.; const int PLANE = 1; const int SPHERE_0 = 2; const int SPHERE_1 = 3; uniform float u_aspect_ratio; varying vec2 v_position; uniform vec3 sphere_position_0; uniform float sphere_radius_0; uniform vec3 sphere_color_0; uniform vec3 sphere_position_1; uniform float sphere_radius_1; uniform vec3 sphere_color_1; uniform vec3 plane_position; uniform vec3 plane_normal; uniform float light_intensity; uniform vec2 light_specular; uniform vec3 light_position; uniform vec3 light_color; uniform float ambient; uniform vec3 O; float intersect_sphere(vec3 O, vec3 D, vec3 S, float R) { float a = dot(D, D); vec3 OS = O - S; float b = 2. * dot(D, OS); float c = dot(OS, OS) - R * R; float disc = b * b - 4. * a * c; if (disc > 0.) { float distSqrt = sqrt(disc); float q = (-b - distSqrt) / 2.0; if (b >= 0.) { q = (-b + distSqrt) / 2.0; } float t0 = q / a; float t1 = c / q; t0 = min(t0, t1); t1 = max(t0, t1); if (t1 >= 0.) { if (t0 < 0.) { return t1; } else { return t0; } } } return INFINITY; } float intersect_plane(vec3 O, vec3 D, vec3 P, vec3 N) { float denom = dot(D, N); if (abs(denom) < 1e-6) { return INFINITY; } float d = dot(P - O, N) / denom; if (d < 0.) { return INFINITY; } return d; } vec3 run(float x, float y) { vec3 Q = vec3(x, y, 0.); vec3 D = normalize(Q - O); int depth = 0; float t_plane, t0, t1; vec3 rayO = O; vec3 rayD = D; vec3 col = vec3(0.0, 0.0, 0.0); vec3 col_ray; float reflection = 1.; int object_index; vec3 object_color; vec3 object_normal; float object_reflection; vec3 M; vec3 N, toL, toO; while (depth < 5) { /* start trace_ray */ t_plane = intersect_plane(rayO, rayD, plane_position, plane_normal); t0 = intersect_sphere(rayO, rayD, sphere_position_0, sphere_radius_0); t1 = intersect_sphere(rayO, rayD, sphere_position_1, sphere_radius_1); if (t_plane < min(t0, t1)) { // Plane. M = rayO + rayD * t_plane; object_normal = plane_normal; // Plane texture. if (mod(int(2*M.x), 2) == mod(int(2*M.z), 2)) { object_color = vec3(1., 1., 1.); } else { object_color = vec3(0., 0., 0.); } object_reflection = .25; object_index = PLANE; } else if (t0 < t1) { // Sphere 0. M = rayO + rayD * t0; object_normal = normalize(M - sphere_position_0); object_color = sphere_color_0; object_reflection = .5; object_index = SPHERE_0; } else if (t1 < t0) { // Sphere 1. M = rayO + rayD * t1; object_normal = normalize(M - sphere_position_1); object_color = sphere_color_1; object_reflection = .5; object_index = SPHERE_1; } else { break; } N = object_normal; toL = normalize(light_position - M); toO = normalize(O - M); // Shadow of the spheres on the plane. if (object_index == PLANE) { t0 = intersect_sphere(M + N * .0001, toL, sphere_position_0, sphere_radius_0); t1 = intersect_sphere(M + N * .0001, toL, sphere_position_1, sphere_radius_1); if (min(t0, t1) < INFINITY) { break; } } col_ray = vec3(ambient, ambient, ambient); col_ray += light_intensity * max(dot(N, toL), 0.) * object_color; col_ray += light_specular.x * light_color * pow(max(dot(N, normalize(toL + toO)), 0.), light_specular.y); /* end trace_ray */ rayO = M + N * .0001; rayD = normalize(rayD - 2. * dot(rayD, N) * N); col += reflection * col_ray; reflection *= object_reflection; depth++; } return clamp(col, 0., 1.); } void main() { vec2 pos = v_position; gl_FragColor = vec4(run(pos.x*u_aspect_ratio, pos.y), 1.); } """ class Canvas(app.Canvas): def __init__(self): app.Canvas.__init__(self, position=(300, 100), size=(800, 600), keys='interactive') self.program = gloo.Program(vertex, fragment) self.program['a_position'] = [(-1., -1.), (-1., +1.), (+1., -1.), (+1., +1.)] self.program['sphere_position_0'] = (.75, .1, 1.) self.program['sphere_radius_0'] = .6 self.program['sphere_color_0'] = (0., 0., 1.) self.program['sphere_position_1'] = (-.75, .1, 2.25) self.program['sphere_radius_1'] = .6 self.program['sphere_color_1'] = (.5, .223, .5) self.program['plane_position'] = (0., -.5, 0.) self.program['plane_normal'] = (0., 1., 0.) self.program['light_intensity'] = 1. self.program['light_specular'] = (1., 50.) self.program['light_position'] = (5., 5., -10.) self.program['light_color'] = (1., 1., 1.) self.program['ambient'] = .05 self.program['O'] = (0., 0., -1.) self._timer = app.Timer('auto', connect=self.on_timer, start=True) def on_timer(self, event): t = event.elapsed self.program['sphere_position_0'] = (+.75, .1, 2.0 + 1.0 * cos(4*t)) self.program['sphere_position_1'] = (-.75, .1, 2.0 - 1.0 * cos(4*t)) self.update() def on_resize(self, event): width, height = event.size gloo.set_viewport(0, 0, width, height) self.program['u_aspect_ratio'] = width/float(height) def on_draw(self, event): self.program.draw('triangle_strip') if __name__ == '__main__': canvas = Canvas() canvas.show() app.run() # In[3]: # Vispy demo : mandelbrot interactive # # http://vispy.org/examples/demo/gloo/mandelbrot.html # -*- coding: utf-8 -*- # vispy: gallery 30 # ----------------------------------------------------------------------------- # Copyright (c) 2014, Vispy Development Team. All Rights Reserved. # Distributed under the (new) BSD License. See LICENSE.txt for more info. # ----------------------------------------------------------------------------- # Author: John David Reaver # Date: 04/29/2014 # ----------------------------------------------------------------------------- from vispy import app, gloo # Shader source code # ----------------------------------------------------------------------------- vertex = """ attribute vec2 position; void main() { gl_Position = vec4(position, 0, 1.0); } """ fragment = """ uniform vec2 resolution; uniform vec2 center; uniform float scale; uniform int iter; // Jet color scheme vec4 color_scheme(float x) { vec3 a, b; float c; if (x < 0.34) { a = vec3(0, 0, 0.5); b = vec3(0, 0.8, 0.95); c = (x - 0.0) / (0.34 - 0.0); } else if (x < 0.64) { a = vec3(0, 0.8, 0.95); b = vec3(0.85, 1, 0.04); c = (x - 0.34) / (0.64 - 0.34); } else if (x < 0.89) { a = vec3(0.85, 1, 0.04); b = vec3(0.96, 0.7, 0); c = (x - 0.64) / (0.89 - 0.64); } else { a = vec3(0.96, 0.7, 0); b = vec3(0.5, 0, 0); c = (x - 0.89) / (1.0 - 0.89); } return vec4(mix(a, b, c), 1.0); } void main() { vec2 z, c; // Recover coordinates from pixel coordinates c.x = (gl_FragCoord.x / resolution.x - 0.5) * scale + center.x; c.y = (gl_FragCoord.y / resolution.y - 0.5) * scale + center.y; // Main Mandelbrot computation int i; z = c; for(i = 0; i < iter; i++) { float x = (z.x * z.x - z.y * z.y) + c.x; float y = (z.y * z.x + z.x * z.y) + c.y; if((x * x + y * y) > 4.0) break; z.x = x; z.y = y; } // Convert iterations to color float color = 1.0 - float(i) / float(iter); gl_FragColor = color_scheme(color); } """ # vispy Canvas # ----------------------------------------------------------------------------- class Canvas(app.Canvas): def __init__(self, *args, **kwargs): app.Canvas.__init__(self, *args, **kwargs) self.program = gloo.Program(vertex, fragment) # Draw a rectangle that takes up the whole screen. All of the work is # done in the shader. self.program["position"] = [(-1, -1), (-1, 1), (1, 1), (-1, -1), (1, 1), (1, -1)] self.scale = self.program["scale"] = 3 self.center = self.program["center"] = [-0.5, 0] self.iterations = self.program["iter"] = 300 self.program['resolution'] = self.size self.bounds = [-2, 2] self.min_scale = 0.00005 self.max_scale = 4 self._timer = app.Timer('auto', connect=self.update, start=True) def on_initialize(self, event): gloo.set_clear_color(color='black') def on_draw(self, event): self.program.draw() def on_resize(self, event): width, height = event.size gloo.set_viewport(0, 0, width, height) self.program['resolution'] = [width, height] def on_mouse_move(self, event): """Pan the view based on the change in mouse position.""" if event.is_dragging and event.buttons[0] == 1: x0, y0 = event.last_event.pos[0], event.last_event.pos[1] x1, y1 = event.pos[0], event.pos[1] X0, Y0 = self.pixel_to_coords(float(x0), float(y0)) X1, Y1 = self.pixel_to_coords(float(x1), float(y1)) self.translate_center(X1 - X0, Y1 - Y0) def translate_center(self, dx, dy): """Translates the center point, and keeps it in bounds.""" center = self.center center[0] -= dx center[1] -= dy center[0] = min(max(center[0], self.bounds[0]), self.bounds[1]) center[1] = min(max(center[1], self.bounds[0]), self.bounds[1]) self.program["center"] = self.center = center def pixel_to_coords(self, x, y): """Convert pixel coordinates to Mandelbrot set coordinates.""" rx, ry = self.size nx = (x / rx - 0.5) * self.scale + self.center[0] ny = ((ry - y) / ry - 0.5) * self.scale + self.center[1] return [nx, ny] def on_mouse_wheel(self, event): """Use the mouse wheel to zoom.""" delta = event.delta[1] if delta > 0: # Zoom in factor = 0.9 elif delta < 0: # Zoom out factor = 1 / 0.9 for _ in range(int(abs(delta))): self.zoom(factor, event.pos) def on_key_press(self, event): """Use + or - to zoom in and out. The mouse wheel can be used to zoom, but some people don't have mouse wheels :) """ if event.text == '+': self.zoom(0.9) elif event.text == '-': self.zoom(1/0.9) def zoom(self, factor, mouse_coords=None): """Factors less than zero zoom in, and greater than zero zoom out. If mouse_coords is given, the point under the mouse stays stationary while zooming. mouse_coords should come from MouseEvent.pos. """ if mouse_coords is not None: # Record the position of the mouse x, y = float(mouse_coords[0]), float(mouse_coords[1]) x0, y0 = self.pixel_to_coords(x, y) self.scale *= factor self.scale = max(min(self.scale, self.max_scale), self.min_scale) self.program["scale"] = self.scale # Translate so the mouse point is stationary if mouse_coords is not None: x1, y1 = self.pixel_to_coords(x, y) self.translate_center(x1 - x0, y1 - y0) if __name__ == '__main__': canvas = Canvas(size=(800, 800), keys='interactive') canvas.show() app.run() # In[5]: # -*- coding: utf-8 -*- """ Demonstrate a simple data-slicing task: given 3D data (displayed at top), select a 2D plane and interpolate data along that plane to generate a slice image (displayed at bottom). """ ## Add path to library (just for examples; you do not need this) import numpy as np from pyqtgraph.Qt import QtCore, QtGui import pyqtgraph as pg app = QtGui.QApplication([]) ## Create window with two ImageView widgets win = QtGui.QMainWindow() win.resize(800,800) win.setWindowTitle('pyqtgraph example: DataSlicing') cw = QtGui.QWidget() win.setCentralWidget(cw) l = QtGui.QGridLayout() cw.setLayout(l) imv1 = pg.ImageView() imv2 = pg.ImageView() l.addWidget(imv1, 0, 0) l.addWidget(imv2, 1, 0) win.show() roi = pg.LineSegmentROI([[10, 64], [120,64]], pen='r') imv1.addItem(roi) x1 = np.linspace(-30, 10, 128)[:, np.newaxis, np.newaxis] x2 = np.linspace(-20, 20, 128)[:, np.newaxis, np.newaxis] y = np.linspace(-30, 10, 128)[np.newaxis, :, np.newaxis] z = np.linspace(-20, 20, 128)[np.newaxis, np.newaxis, :] d1 = np.sqrt(x1**2 + y**2 + z**2) d2 = 2*np.sqrt(x1[::-1]**2 + y**2 + z**2) d3 = 4*np.sqrt(x2**2 + y[:,::-1]**2 + z**2) data = (np.sin(d1) / d1**2) + (np.sin(d2) / d2**2) + (np.sin(d3) / d3**2) def update(): global data, imv1, imv2 d2 = roi.getArrayRegion(data, imv1.imageItem, axes=(1,2)) imv2.setImage(d2) roi.sigRegionChanged.connect(update) ## Display the data imv1.setImage(data) imv1.setHistogramRange(-0.01, 0.01) imv1.setLevels(-0.003, 0.003) update() ## Start Qt event loop unless running in interactive mode. if __name__ == '__main__': import sys if (sys.flags.interactive != 1) or not hasattr(QtCore, 'PYQT_VERSION'): QtGui.QApplication.instance().exec_() # In[ ]: