summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xcamera.py117
-rw-r--r--color/chromaticity.py12
-rw-r--r--detectors/__init__.py9
-rw-r--r--detectors/lbne.py22
-rw-r--r--detectors/sno.py12
-rw-r--r--fileio/root.py2
-rw-r--r--generator/g4gen.py2
-rw-r--r--generator/vertex.py4
-rw-r--r--geometry.py6
-rw-r--r--gpu.py15
-rw-r--r--make.py20
-rw-r--r--models/__init__.py3
-rw-r--r--optics.py2
-rw-r--r--sample.py2
-rw-r--r--scenes/checkerboard.py16
-rw-r--r--solids/__init__.py21
-rw-r--r--solids/pmts.py14
-rw-r--r--src/__init__.py9
-rw-r--r--stl.py2
-rwxr-xr-xview.py375
20 files changed, 179 insertions, 486 deletions
diff --git a/camera.py b/camera.py
index fa38060..7d23be5 100755
--- a/camera.py
+++ b/camera.py
@@ -4,12 +4,15 @@ from itertools import product, count
from threading import Thread, Lock
import os
import sys
-from color import map_wavelength, map_to_color
+from chroma.color import map_wavelength, map_to_color
+from chroma.geometry import Mesh, Solid, Geometry
+import chroma.make as make
import matplotlib.pyplot as plt
-from gpu import GPU, CUDAFuncs
-from tools import timeit
-from transform import rotate
+from chroma.gpu import GPU, CUDAFuncs
+from chroma.tools import timeit
+from chroma.transform import rotate
+from chroma.optics import vacuum, lambertian_surface
import pygame
from pygame.locals import *
@@ -22,6 +25,65 @@ from subprocess import call
import shutil
import tempfile
+def buildable(identifier):
+ """
+ Create a decorator which tags a function as buildable and assigns the
+ identifying string `identifier`.
+
+ Example:
+ >>> @buildable('my_sphere')
+ >>> def build_my_sphere():
+ >>> g = Geometry()
+ >>> g.add_solid(Solid(sphere(), vacuum, water))
+ >>> return g
+ """
+ def tag_as_buildable(func):
+ func.buildable = True
+ func.identifier = identifier
+ return func
+ return tag_as_buildable
+
+def build(obj, bits):
+ """Construct and build a geometry from `obj`."""
+ if inspect.isfunction(obj):
+ try:
+ if obj.buildable:
+ obj = obj()
+ except AttributeError:
+ raise Exception('function %s is not buildable.' % obj.__name__)
+
+ if isinstance(obj, Geometry):
+ geometry = obj
+ elif isinstance(obj, Solid):
+ geometry = Geometry()
+ geometry.add_solid(obj)
+ elif isinstance(obj, Mesh):
+ geometry = Geometry()
+ geometry.add_solid(Solid(obj, vacuum, vacuum, surface=lambertian_surface, color=0x99ffffff))
+ else:
+ raise Exception('cannot build type %s' % type(obj))
+
+ geometry.build(bits)
+
+ return geometry
+
+def bvh_mesh(geometry, layer):
+ lower_bounds = geometry.lower_bounds[geometry.layers == layer]
+ upper_bounds = geometry.upper_bounds[geometry.layers == layer]
+
+ if len(lower_bounds) == 0 or len(upper_bounds) == 0:
+ raise Exception('no nodes at layer %i' % layer)
+
+ dx, dy, dz = upper_bounds[0] - lower_bounds[0]
+ center = np.mean([upper_bounds[0],lower_bounds[0]], axis=0)
+
+ mesh = make.box(dx, dy, dz, center)
+
+ for center, dx, dy, dz in zip(np.mean([lower_bounds,upper_bounds],axis=0),*zip(*upper_bounds-lower_bounds))[1:]:
+ mesh += make.box(dx,dy,dz,center)
+
+ return mesh
+
def encode_movie(dir):
root, ext = 'movie', 'avi'
for i in count():
@@ -59,6 +121,10 @@ class Camera(Thread):
self.device_id = device_id
self.size = size
+ self.unique_bvh_layers = np.unique(self.geometry.layers)
+ self.currentlayer = None
+ self.bvh_layers = {self.currentlayer : self.geometry}
+
try:
import spnav as spnav_module
self.spnav_module = spnav_module
@@ -231,6 +297,16 @@ class Camera(Thread):
self.screenshot(self.movie_dir, self.movie_index)
self.movie_index += 1
+ def loadlayer(self, layer):
+ try:
+ layergeometry = self.bvh_layers[layer]
+ except KeyError:
+ layergeometry = build(bvh_mesh(self.geometry, layer),8)
+ self.bvh_layers[layer] = layergeometry
+
+ self.gpu.load_geometry(layergeometry)
+ self.update()
+
def process_event(self, event):
if event.type == MOUSEBUTTONDOWN:
if event.button == 4:
@@ -310,6 +386,28 @@ class Camera(Thread):
self.done = True
return
+ elif event.key == K_PAGEDOWN:
+ if self.currentlayer is None:
+ self.currentlayer = self.unique_bvh_layers[-1]
+ else:
+ if self.currentlayer > np.min(self.unique_bvh_layers):
+ self.currentlayer -= 1
+ else:
+ self.currentlayer = None
+
+ self.loadlayer(self.currentlayer)
+
+ elif event.key == K_PAGEUP:
+ if self.currentlayer is None:
+ self.currentlayer = self.unique_bvh_layers[0]
+ else:
+ if self.currentlayer < np.max(self.unique_bvh_layers):
+ self.currentlayer += 1
+ else:
+ self.currentlayer = None
+
+ self.loadlayer(self.currentlayer)
+
elif event.key == K_F12:
self.screenshot()
@@ -483,11 +581,10 @@ if __name__ == '__main__':
import optparse
import inspect
- import solids
- import detectors
- import scenes
- from stl import mesh_from_stl
- from view import build
+ import chroma.solids
+ import chroma.detectors
+ import chroma.scenes
+ from chroma.stl import mesh_from_stl
parser = optparse.OptionParser('%prog filename.stl')
parser.add_option('-b', '--bits', type='int', dest='bits',
@@ -511,7 +608,7 @@ if __name__ == '__main__':
obj = mesh_from_stl(args[0])
else:
- members = dict(inspect.getmembers(detectors) + inspect.getmembers(solids) + inspect.getmembers(scenes))
+ members = dict(inspect.getmembers(chroma.detectors) + inspect.getmembers(chroma.solids) + inspect.getmembers(chroma.scenes))
buildable_lookup = {}
for member in members.values():
diff --git a/color/chromaticity.py b/color/chromaticity.py
index 859cc14..0076957 100644
--- a/color/chromaticity.py
+++ b/color/chromaticity.py
@@ -1,14 +1,8 @@
import numpy as np
-import os
-import sys
+from os.path import realpath, dirname
+from chroma.tools import read_csv
-dir = os.path.split(os.path.realpath(__file__))[0]
-
-sys.path.append(dir + '/..')
-
-from tools import read_csv
-
-color_map = read_csv(dir + '/ciexyz64_1.csv')
+color_map = read_csv(dirname(realpath(__file__)) + '/ciexyz64_1.csv')
def map_wavelength(wavelength):
r = np.interp(wavelength, color_map[:,0], color_map[:,1])
diff --git a/detectors/__init__.py b/detectors/__init__.py
index 8550751..f812058 100644
--- a/detectors/__init__.py
+++ b/detectors/__init__.py
@@ -1,15 +1,8 @@
from lbne import build_lbne
from sno import build_sno as build_sno_detector
-
-import os
-import sys
+from chroma.camera import buildable
import inspect
-dir = os.path.split(os.path.realpath(__file__))[0]
-sys.path.append(dir + '/..')
-
-from view import buildable
-
# from LBNE document #3951
radius = 63.30/2
height = 76.60
diff --git a/detectors/lbne.py b/detectors/lbne.py
index 8942cb2..ca13c2d 100644
--- a/detectors/lbne.py
+++ b/detectors/lbne.py
@@ -1,27 +1,21 @@
-import os
-import sys
import numpy as np
-
-dir = os.path.split(os.path.realpath(__file__))[0]
-sys.path.append(dir + '/..')
-
-from geometry import *
-from solids import build_12inch_pmt, build_12inch_pmt_with_lc, build_12inch_pmt_shell
-from optics import *
-from transform import rotate, make_rotation_matrix
+from chroma.geometry import Solid, Geometry
+import chroma.solids as solids
+from chroma.optics import vacuum, water, water_wcsim, black_surface
+from chroma.transform import rotate, make_rotation_matrix
from itertools import product
-from make import cylinder, segmented_cylinder
+import chroma.make as make
def build_lbne(radius, height, nstrings, pmts_per_string, endcap_spacing, physical_model=True):
if physical_model:
- pmt = build_12inch_pmt_with_lc(outer_material=water_wcsim)
+ pmt = solids.build_12inch_pmt_with_lc(outer_material=water_wcsim)
else:
- pmt = build_12inch_pmt_shell(outer_material=water_wcsim)
+ pmt = solids.build_12inch_pmt_shell(outer_material=water_wcsim)
lbne = Geometry()
# outer cylinder
- cylinder_mesh = segmented_cylinder(radius, height+height/(pmts_per_string-1), nsteps=16*nstrings, nsegments=1200)
+ cylinder_mesh = make.segmented_cylinder(radius, height+height/(pmts_per_string-1), nsteps=16*nstrings, nsegments=1200)
cylinder_mesh.vertices = rotate(cylinder_mesh.vertices, np.pi/2, (-1,0,0))
lbne.add_solid(Solid(cylinder_mesh, water_wcsim, vacuum, black_surface, 0xff0000ff))
diff --git a/detectors/sno.py b/detectors/sno.py
index 3e748b4..d0334d3 100644
--- a/detectors/sno.py
+++ b/detectors/sno.py
@@ -1,12 +1,12 @@
import numpy as np
import numpy.linalg
import math
-from make import rotate_extrude
-from stl import mesh_from_stl
-from geometry import *
-from optics import *
-from solids import build_8inch_pmt_with_lc
-from transform import rotate, make_rotation_matrix
+from chroma.make import rotate_extrude
+from chroma.stl import mesh_from_stl
+from chroma.geometry import *
+from chroma.optics import *
+from chroma.solids import build_8inch_pmt_with_lc
+from chroma.transform import rotate, make_rotation_matrix
import os
def sno_vessel(sphere_radius, neck_radius, neck_top, nsteps=40):
diff --git a/fileio/root.py b/fileio/root.py
index 77c23ff..ae9e741 100644
--- a/fileio/root.py
+++ b/fileio/root.py
@@ -4,7 +4,7 @@ import os.path
ROOT.gROOT.ProcessLine('.L '+os.path.join(os.path.dirname(__file__), 'root.C+g'))
import ROOT
-import event
+import chroma.event as event
class RootWriter(object):
def __init__(self, filename):
diff --git a/generator/g4gen.py b/generator/g4gen.py
index cec53f7..b43ce92 100644
--- a/generator/g4gen.py
+++ b/generator/g4gen.py
@@ -4,7 +4,7 @@ import g4py.NISTmaterials
import g4py.ParticleGun
import pyublas
import numpy as np
-import event
+import chroma.event as event
try:
import G4chroma
diff --git a/generator/vertex.py b/generator/vertex.py
index 1fa61cb..3998e6e 100644
--- a/generator/vertex.py
+++ b/generator/vertex.py
@@ -3,8 +3,8 @@ import numpy as np
from math import sin, cos, sqrt
import copy
-import pi0
-from event import Event, Subtrack
+import chroma.pi0 as pi0
+from chroma.event import Event, Subtrack
# generator parts for use with gun()
diff --git a/geometry.py b/geometry.py
index 856ded3..6ea8994 100644
--- a/geometry.py
+++ b/geometry.py
@@ -1,8 +1,8 @@
import sys
import os
import numpy as np
-from itertoolset import *
-from tools import timeit, profile_if_possible
+from chroma.itertoolset import *
+from chroma.tools import timeit, profile_if_possible
from hashlib import md5
import cPickle as pickle
import gzip
@@ -274,7 +274,7 @@ class Geometry(object):
try:
self.surface_index[self.surface_index == surface_lookup[None]] = -1
- except ValueError:
+ except KeyError:
pass
checksum = md5(str(bits))
diff --git a/gpu.py b/gpu.py
index 327e692..372bc7b 100644
--- a/gpu.py
+++ b/gpu.py
@@ -7,11 +7,12 @@ import pycuda.driver as cuda
from pycuda import gpuarray
from copy import copy
from itertools import izip
-from tools import timeit
+from chroma.tools import timeit
+from os.path import dirname
-import src
-from geometry import standard_wavelengths
-from color import map_to_color
+import chroma.src
+from chroma.geometry import standard_wavelengths
+from chroma.color import map_to_color
import sys
import event
@@ -97,15 +98,15 @@ class GPU(object):
self.context.set_cache_config(cuda.func_cache.PREFER_L1)
- cuda_options = ['-I' + src.dir, '--use_fast_math', '--ptxas-options=-v']
+ cuda_options = ['-I' + dirname(chroma.src.__file__), '--use_fast_math', '--ptxas-options=-v']
- self.module = SourceModule(src.kernel, options=cuda_options, no_extern_c=True)
+ self.module = SourceModule(chroma.src.kernel, options=cuda_options, no_extern_c=True)
self.geo_funcs = CUDAFuncs(self.module, ['set_wavelength_range', 'set_material', 'set_surface', 'set_global_mesh_variables', 'color_solids'])
self.prop_funcs = CUDAFuncs(self.module, ['init_rng', 'propagate', 'swap'])
self.nthread_per_block = 64
self.max_blocks = 1024
- self.daq_module = SourceModule(src.daq, options=cuda_options, no_extern_c=True)
+ self.daq_module = SourceModule(chroma.src.daq, options=cuda_options, no_extern_c=True)
self.daq_funcs = CUDAFuncs(self.daq_module,
['reset_earliest_time_int', 'run_daq',
'convert_sortable_int_to_float'])
diff --git a/make.py b/make.py
index 1da5d0e..523b10f 100644
--- a/make.py
+++ b/make.py
@@ -1,12 +1,12 @@
import numpy as np
-from geometry import Mesh
-from transform import rotate
-from itertoolset import *
+from chroma.geometry import Mesh
+from chroma.transform import rotate
+from chroma.itertoolset import *
def mesh_grid(grid):
return np.vstack(zip(grid[:-1].flatten(),grid[1:].flatten(),np.roll(grid[1:],-1,1).flatten()) + zip(grid[:-1].flatten(),np.roll(grid[1:],-1,1).flatten(),np.roll(grid[:-1],-1,1).flatten()))
-def linear_extrude(x1, y1, height, x2=None, y2=None):
+def linear_extrude(x1, y1, height, x2=None, y2=None, center=None):
"""
Return the solid mesh formed by linearly extruding the polygon formed by
the x and y points `x1` and `y1` by a distance `height`. If `x2` and `y2`
@@ -41,6 +41,9 @@ def linear_extrude(x1, y1, height, x2=None, y2=None):
vertices = np.fromiter(flatten(roundrobin(*vertex_iterators)), float)
vertices = vertices.reshape((len(vertices)//3,3))
+ if center is not None:
+ vertices += center
+
triangles = mesh_grid(np.arange(len(vertices)).reshape((len(x1),len(vertices)//len(x1))).transpose()[::-1])
return Mesh(vertices, triangles, remove_duplicate_vertices=True)
@@ -65,8 +68,15 @@ def rotate_extrude(x, y, nsteps=64):
return Mesh(vertices, triangles, remove_duplicate_vertices=True)
-def cube(size=1):
+def box(dx, dy, dz, center=(0,0,0)):
+ "Return a box with linear dimensions `dx`, `dy`, and `dz`."
+ return linear_extrude([-dx/2.0,dx/2.0,dx/2.0,-dx/2.0],[-dy/2.0,-dy/2.0,dy/2.0,dy/2.0],height=dz,center=center)
+
+def cube(size=1, height=None):
"Return a cube mesh whose sides have length `size`."
+ if height is None:
+ height = size
+
return linear_extrude([-size/2.0,size/2.0,size/2.0,-size/2.0],[-size/2.0,-size/2.0,size/2.0,size/2.0], height=size)
def cylinder(radius=1, height=2, radius2=None, nsteps=64):
diff --git a/models/__init__.py b/models/__init__.py
deleted file mode 100644
index f369c9b..0000000
--- a/models/__init__.py
+++ /dev/null
@@ -1,3 +0,0 @@
-import os
-
-dir = os.path.split(os.path.realpath(__file__))[0]
diff --git a/optics.py b/optics.py
index 4e7530e..02b8e0d 100644
--- a/optics.py
+++ b/optics.py
@@ -1,5 +1,5 @@
import numpy as np
-from geometry import Material, Surface
+from chroma.geometry import Material, Surface
vacuum = Material('vacuum')
vacuum.set('refractive_index', 1.0)
diff --git a/sample.py b/sample.py
index 0b2ffc6..1909370 100644
--- a/sample.py
+++ b/sample.py
@@ -1,5 +1,5 @@
import numpy as np
-from transform import rotate
+from chroma.transform import rotate
def uniform_sphere(size=None, dtype=np.double):
"""
diff --git a/scenes/checkerboard.py b/scenes/checkerboard.py
index d2a9ec8..7e4f755 100644
--- a/scenes/checkerboard.py
+++ b/scenes/checkerboard.py
@@ -1,15 +1,9 @@
-import os
-import sys
-
-dir = os.path.split(os.path.realpath(__file__))[0]
-sys.path.append(dir + '/..')
-
import numpy as np
-from itertoolset import *
-from geometry import Mesh, Solid, Geometry
-from optics import *
-from make import sphere
-from view import buildable
+from chroma.itertoolset import *
+from chroma.geometry import Mesh, Solid, Geometry
+from chroma.optics import *
+from chroma.make import sphere
+from chroma.camera import buildable
@buildable('checkerboard_scene')
def build_checkerboard_scene(checkers_per_side=10, squares_per_checker=50):
diff --git a/solids/__init__.py b/solids/__init__.py
index a24ce9c..421b66f 100644
--- a/solids/__init__.py
+++ b/solids/__init__.py
@@ -1,23 +1,16 @@
import numpy as np
-
from pmts import build_pmt, build_light_collector, build_light_collector_from_file, build_pmt_shell
-
-import os
-import sys
-
-dir = os.path.split(os.path.realpath(__file__))[0]
-sys.path.append(dir + '/..')
-
-from optics import *
-from view import buildable
+from chroma.optics import *
+from chroma.camera import buildable
+from os.path import dirname
@buildable('12inch_pmt')
def build_12inch_pmt(outer_material=water, nsteps=16):
- return build_pmt(dir + '/hamamatsu_12inch.txt', 0.003, outer_material, nsteps)
+ return build_pmt(dirname(__file__) + '/hamamatsu_12inch.txt', 0.003, outer_material, nsteps)
@buildable('12inch_pmt_shell')
def build_12inch_pmt_shell(outer_material=water, nsteps=16):
- return build_pmt_shell(dir + '/hamamatsu_12inch.txt')
+ return build_pmt_shell(dirname(__file__) + '/hamamatsu_12inch.txt')
# from Jelena Maricic
lc_12inch_a = 0.16597
@@ -39,10 +32,10 @@ def build_12inch_pmt_with_lc_hd(outer_material=water, nsteps=128):
@buildable('8inch_pmt')
def build_8inch_pmt(outer_material=water, nsteps=24):
- return build_pmt(dir + '/sno_pmt_reduced.txt', 0.003, outer_material, nsteps)
+ return build_pmt(dirname(__file__) + '/sno_pmt_reduced.txt', 0.003, outer_material, nsteps)
@buildable('8inch_pmt_with_lc')
def build_8inch_pmt_with_lc(outer_material=water, nsteps=24):
pmt = build_8inch_pmt(outer_material, nsteps)
- lc = build_light_collector_from_file(dir + '/sno_cone.txt', outer_material, nsteps)
+ lc = build_light_collector_from_file(dirname(__file__) + '/sno_cone.txt', outer_material, nsteps)
return pmt + lc
diff --git a/solids/pmts.py b/solids/pmts.py
index fcbc8fc..43aed3f 100644
--- a/solids/pmts.py
+++ b/solids/pmts.py
@@ -1,14 +1,8 @@
-import os
-import sys
-
-dir = os.path.split(os.path.realpath(__file__))[0]
-sys.path.append(dir + '/..')
-
import numpy as np
-from geometry import Solid
-from make import rotate_extrude
-from optics import *
-from tools import read_csv, offset
+from chroma.geometry import Solid
+from chroma.make import rotate_extrude
+from chroma.optics import *
+from chroma.tools import read_csv, offset
def get_lc_profile(radii, a, b, d, rmin, rmax):
c = -b*np.sqrt(1 - (rmin-d)**2/a**2)
diff --git a/src/__init__.py b/src/__init__.py
index 865d612..f2f5215 100644
--- a/src/__init__.py
+++ b/src/__init__.py
@@ -1,6 +1,7 @@
-import os
+from os.path import dirname
-dir = os.path.split(os.path.realpath(__file__))[0]
+with open(dirname(__file__) + '/kernel.cu') as f:
+ kernel = f.read()
-kernel = open(dir + '/kernel.cu').read()
-daq = open(dir + '/daq.cu').read()
+with open(dirname(__file__) + '/daq.cu') as f:
+ daq = f.read()
diff --git a/stl.py b/stl.py
index 9bc14de..0806c29 100644
--- a/stl.py
+++ b/stl.py
@@ -1,7 +1,7 @@
import numpy as np
import string
import struct
-from geometry import Mesh
+from chroma.geometry import Mesh
import bz2
def mesh_from_stl(filename):
diff --git a/view.py b/view.py
deleted file mode 100755
index 7ae6a27..0000000
--- a/view.py
+++ /dev/null
@@ -1,375 +0,0 @@
-#!/usr/bin/env python
-import os
-import sys
-import time
-import numpy as np
-import inspect
-
-import pygame
-from pygame.locals import *
-
-import src
-from camera import get_rays
-from geometry import Mesh, Solid, Geometry
-from transform import rotate
-from optics import *
-from gpu import *
-
-#from pycuda import autoinit
-from pycuda.compiler import SourceModule
-from pycuda import gpuarray
-import pycuda.driver as cuda
-
-def buildable(identifier):
- """
- Create a decorator which tags a function as buildable and assigns the
- identifying string `identifier`.
-
- Example:
- >>> @buildable('my_sphere')
- >>> def build_my_sphere():
- >>> g = Geometry()
- >>> g.add_solid(Solid(sphere(), vacuum, water))
- >>> return g
- """
- def tag_as_buildable(func):
- func.buildable = True
- func.identifier = identifier
- return func
- return tag_as_buildable
-
-def screenshot(screen, name='', dir='', index=0):
- """Take a screenshot of `screen`."""
- if name == '':
- root, ext = 'screenshot', 'png'
- else:
- root, ext = name, 'png'
-
- i = index
-
- filename = os.path.join(dir,'.'.join([root + str(i).zfill(4), ext]))
- while os.path.exists(filename):
- filename = os.path.join(dir,'.'.join([root + str(i).zfill(4), ext]))
- i += 1
-
- pygame.image.save(screen, filename)
- print 'image saved to %s' % filename
-
-def build(obj, bits):
- """Construct and build a geometry from `obj`."""
- if inspect.isfunction(obj):
- try:
- if obj.buildable:
- obj = obj()
- except AttributeError:
- raise Exception('function %s is not buildable.' % obj.__name__)
-
- if isinstance(obj, Geometry):
- geometry = obj
- elif isinstance(obj, Solid):
- geometry = Geometry()
- geometry.add_solid(obj)
- elif isinstance(obj, Mesh):
- geometry = Geometry()
- geometry.add_solid(Solid(obj, vacuum, vacuum, surface=lambertian_surface, color=0x99ffffff))
- else:
- raise Exception('cannot build type %s' % type(obj))
-
- geometry.build(bits)
-
- return geometry
-
-def box(lower_bound, upper_bound):
- """
- Return a mesh of the box defined by the opposing corners `lower_bound`
- and `upper_bound`.
- """
- dx, dy, dz = upper_bound - lower_bound
-
- vertices = np.array([lower_bound,
- lower_bound + (dx,0,0),
- lower_bound + (dx,dy,0),
- lower_bound + (0,dy,0),
- lower_bound + (0,0,dz),
- lower_bound + (dx,0,dz),
- lower_bound + (dx,dy,dz),
- lower_bound + (0,dy,dz)])
-
- triangles = np.empty((12,3), dtype=np.int32)
- # bottom
- triangles[0] = (1,3,2)
- triangles[1] = (1,4,3)
- # top
- triangles[2] = (5,7,6)
- triangles[3] = (5,8,7)
- # left
- triangles[4] = (5,1,2)
- triangles[5] = (5,2,6)
- # right
- triangles[6] = (3,4,8)
- triangles[7] = (3,8,7)
- # front
- triangles[8] = (2,3,7)
- triangles[9] = (2,7,6)
- # back
- triangles[10] = (1,5,8)
- triangles[11] = (1,8,4)
-
- triangles -= 1
-
- return Mesh(vertices, triangles)
-
-def bvh_mesh(geometry, layer):
- lower_bounds = geometry.lower_bounds[geometry.layers == layer]
- upper_bounds = geometry.upper_bounds[geometry.layers == layer]
-
- if len(lower_bounds) == 0 or len(upper_bounds) == 0:
- raise Exception('no nodes at layer %i' % layer)
-
- mesh = box(lower_bounds[0], upper_bounds[0])
-
- for lower_bound, upper_bound in zip(lower_bounds, upper_bounds)[1:]:
- mesh += box(lower_bound, upper_bound)
-
- return mesh
-
-def view(viewable, size=(800,600), name='', bits=8, load_bvh=False):
- """
- Render `viewable` in a pygame window.
-
- Movement:
- - zoom: scroll the mouse wheel
- - rotate: click and drag the mouse
- - move: shift+click and drag the mouse
- """
-
- gpu = GPU()
-
- geometry = build(viewable, bits)
-
- if load_bvh:
- print 'loading bvh...'
- bvhg = []
-
- bvhg.append(geometry)
-
- for layer in sorted(np.unique(geometry.layers)):
- print 'building layer %i' % layer
- bvhg.append(build(bvh_mesh(geometry, layer), bits))
-
- lower_bound, upper_bound = geometry.mesh.get_bounds()
-
- scale = np.linalg.norm(upper_bound-lower_bound)
-
- #from pycuda import autoinit
-
- #print 'device %s' % autoinit.device.name()
-
- module = gpu.module
-
- #module = SourceModule(src.kernel, options=['-I' + src.dir], no_extern_c=True)#, cache_dir=False)
- #geometry.load(module)
- gpu.load_geometry(geometry)
- cuda_raytrace = module.get_function('ray_trace')
- cuda_rotate = module.get_function('rotate')
- cuda_translate = module.get_function('translate')
-
- pygame.init()
- width, height = size
- screen = pygame.display.set_mode(size)
- pygame.display.set_caption(name)
-
- #camera = Camera(size)
-
- diagonal = np.linalg.norm(upper_bound-lower_bound)
-
- point = np.array([0, diagonal*1.75, (lower_bound[2]+upper_bound[2])/2])
- axis1 = np.array([1,0,0], dtype=np.double)
- axis2 = np.array([0,0,1], dtype=np.double)
-
- #camera.position(point)
-
- origins, directions = get_rays(point, size)
-
- origins_gpu = gpuarray.to_gpu(origins.astype(np.float32).view(gpuarray.vec.float3))
-
- directions_gpu = gpuarray.to_gpu(directions.astype(np.float32).view(gpuarray.vec.float3))
-
- pixels_gpu = gpuarray.zeros(width*height, dtype=np.int32)
-
- nblocks = 64
-
- def update():
- """Render the mesh and display to screen."""
- t0 = time.time()
- cuda_raytrace(np.int32(pixels_gpu.size), origins_gpu, directions_gpu, pixels_gpu, block=(nblocks,1,1), grid=(pixels_gpu.size//nblocks+1,1))
- cuda.Context.synchronize()
- elapsed = time.time() - t0
-
- #print 'elapsed %f sec' % elapsed
-
- pygame.surfarray.blit_array(screen, pixels_gpu.get().reshape(size))
- pygame.display.flip()
-
- update()
-
- done = False
- clicked = False
- shift = False
-
- current_layer = 0
-
- while not done:
- for event in pygame.event.get():
- if event.type == MOUSEBUTTONDOWN:
- if event.button == 4:
- v = scale*np.cross(axis1,axis2)/10.0
-
- cuda_translate(np.int32(pixels_gpu.size), origins_gpu, gpuarray.vec.make_float3(*v), block=(nblocks,1,1), grid=(pixels_gpu.size//nblocks+1,1))
-
- point += v
-
- update()
-
- if event.button == 5:
- v = -scale*np.cross(axis1,axis2)/10.0
-
- cuda_translate(np.int32(pixels_gpu.size), origins_gpu, gpuarray.vec.make_float3(*v), block=(nblocks,1,1), grid=(pixels_gpu.size//nblocks+1,1))
-
- point += v
-
- update()
-
- if event.button == 1:
- clicked = True
- mouse_position = pygame.mouse.get_rel()
-
- if event.type == MOUSEBUTTONUP:
- if event.button == 1:
- clicked = False
-
- if event.type == MOUSEMOTION and clicked:
- movement = np.array(pygame.mouse.get_rel())
-
- if (movement == 0).all():
- continue
-
- length = np.linalg.norm(movement)
-
- mouse_direction = movement[0]*axis1 + movement[1]*axis2
- mouse_direction /= np.linalg.norm(mouse_direction)
-
- if shift:
- v = mouse_direction*scale*length/float(width)
-
- cuda_translate(np.int32(pixels_gpu.size), origins_gpu, gpuarray.vec.make_float3(*v), block=(nblocks,1,1), grid=(pixels_gpu.size//nblocks+1,1))
-
- point += v
-
- update()
- else:
- phi = np.float32(2*np.pi*length/float(width))
- n = rotate(mouse_direction, np.pi/2, \
- -np.cross(axis1,axis2))
-
- cuda_rotate(np.int32(pixels_gpu.size), origins_gpu, phi, gpuarray.vec.make_float3(*n), block=(nblocks,1,1), grid=(pixels_gpu.size//nblocks+1,1))
-
- cuda_rotate(np.int32(pixels_gpu.size), directions_gpu, phi, gpuarray.vec.make_float3(*n), block=(nblocks,1,1), grid=(pixels_gpu.size//nblocks+1,1))
-
- point = rotate(point, phi, n)
- axis1 = rotate(axis1, phi, n)
- axis2 = rotate(axis2, phi, n)
-
- update()
-
- if event.type == KEYDOWN:
- if event.key == K_LSHIFT or event.key == K_RSHIFT:
- shift = True
-
- if event.key == K_ESCAPE:
- done = True
- break
-
- if event.key == K_PAGEUP and load_bvh:
- try:
- if current_layer+1 >= len(bvhg):
- raise IndexError
-
- geometry = bvhg[current_layer+1]
- current_layer += 1
-
- gpu.load_geometry(geometry)
- #geometry.load(module, color=True)
- update()
- except IndexError:
- print 'no further layers to view'
-
- if event.key == K_PAGEDOWN and load_bvh:
- try:
- if current_layer-1 < 0:
- raise IndexError
-
- geometry = bvhg[current_layer-1]
- current_layer -= 1
-
- gpu.load_geometry(geometry)
- #geometry.load(module, color=True)
- update()
- except IndexError:
- print 'no further layers to view'
-
- if event.key == K_F12:
- screenshot(screen, name)
-
- if event.type == KEYUP:
- if event.key == K_LSHIFT or event.key == K_RSHIFT:
- shift = False
-
- if event.type == pygame.QUIT:
- done = True
- break
-
- pygame.display.quit()
-
-if __name__ == '__main__':
- import optparse
-
- from stl import mesh_from_stl
-
- import solids
- import detectors
- import scenes
-
- parser = optparse.OptionParser('%prog filename.stl')
- parser.add_option('-b', '--bits', type='int', dest='bits',
- help='bits for z-ordering space axes', default=8)
- parser.add_option('-l', action='store_true', dest='load_bvh',
- help='load bounding volumes', default=False)
- parser.add_option('-r', '--resolution', dest='resolution',
- help='specify resolution', default='800,600')
- options, args = parser.parse_args()
-
- if len(args) < 1:
- sys.exit(parser.format_help())
-
- size = [int(s) for s in options.resolution.split(',')]
-
- if os.path.exists(args[0]):
- head, tail = os.path.split(args[0])
- root, ext = os.path.splitext(tail)
-
- if ext.lower() in ('.stl', '.bz2'):
- view(mesh_from_stl(args[0]), size, root, options.bits, options.load_bvh)
- else:
- members = dict(inspect.getmembers(detectors) + inspect.getmembers(solids) + inspect.getmembers(scenes))
-
- buildable_lookup = {}
- for member in members.values():
- if inspect.isfunction(member) and \
- hasattr(member, 'buildable') and member.buildable == True:
- buildable_lookup[member.identifier] = member
-
- if args[0] in buildable_lookup:
- view(buildable_lookup[args[0]], size, args[0], options.bits, options.load_bvh)
- else:
- sys.exit("couldn't find object %s" % args[0])