summaryrefslogtreecommitdiff
path: root/chroma/detectors
diff options
context:
space:
mode:
authorStan Seibert <stan@mtrr.org>2011-09-19 14:36:13 -0400
committerStan Seibert <stan@mtrr.org>2011-09-19 14:36:13 -0400
commita21b05e4727403e2e061234289af9e60e6022e5a (patch)
tree7a7d4c5809c370f3e542cfc8cb0bec7c2e4f5cdc /chroma/detectors
parentcfecff941fc619eb7269128afc62d9c11ae78aff (diff)
parenta38c56ff1e268298568077af7f03c8ac64c6fb82 (diff)
downloadchroma-a21b05e4727403e2e061234289af9e60e6022e5a.tar.gz
chroma-a21b05e4727403e2e061234289af9e60e6022e5a.tar.bz2
chroma-a21b05e4727403e2e061234289af9e60e6022e5a.zip
merge relayout branch
Diffstat (limited to 'chroma/detectors')
-rw-r--r--chroma/detectors/__init__.py35
-rw-r--r--chroma/detectors/lbne.py49
-rw-r--r--chroma/detectors/miniclean.py80
-rw-r--r--chroma/detectors/miniclean_cassettes.txt92
-rw-r--r--chroma/detectors/miniclean_polygons.txt3
-rw-r--r--chroma/detectors/sno.py133
-rw-r--r--chroma/detectors/sno_av_ascii.stl.bz2bin0 -> 10939133 bytes
-rw-r--r--chroma/detectors/sno_pmt_info.hdf5bin0 -> 128083 bytes
8 files changed, 392 insertions, 0 deletions
diff --git a/chroma/detectors/__init__.py b/chroma/detectors/__init__.py
new file mode 100644
index 0000000..2028300
--- /dev/null
+++ b/chroma/detectors/__init__.py
@@ -0,0 +1,35 @@
+from lbne import build_lbne
+from sno import build_sno as build_sno_detector
+from miniclean import build_miniclean as build_miniclean_detector
+
+# from LBNE document #3951
+radius = 63.30/2
+height = 76.60
+nstrings = 230
+pmts_per_string = 88
+endcap_spacing = 0.86
+
+def lbne_event_view():
+ return build_lbne(radius, height, nstrings, pmts_per_string,
+ endcap_spacing, physical_model=False)
+
+def lbne():
+ return build_lbne(radius, height, nstrings, pmts_per_string,
+ endcap_spacing)
+
+def minilbne():
+ return build_lbne(radius/10, height/10, nstrings//10, pmts_per_string//10,
+ endcap_spacing)
+
+def microlbne():
+ return build_lbne(radius/40, height/40, nstrings//40, pmts_per_string//40,
+ endcap_spacing)
+
+def sno():
+ return build_sno_detector()
+
+def cad_sno():
+ return build_sno_detector(real_av=True)
+
+def miniclean():
+ return build_miniclean_detector()
diff --git a/chroma/detectors/lbne.py b/chroma/detectors/lbne.py
new file mode 100644
index 0000000..97d09e9
--- /dev/null
+++ b/chroma/detectors/lbne.py
@@ -0,0 +1,49 @@
+import numpy as np
+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
+import chroma.make as make
+
+def build_lbne(radius, height, nstrings, pmts_per_string, endcap_spacing, detector_material=water_wcsim, physical_model=True):
+ if physical_model:
+ pmt = solids.build_12inch_pmt_with_lc(outer_material=detector_material)
+ else:
+ pmt = solids.build_12inch_pmt_shell(outer_material=detector_material)
+
+ lbne = Geometry(detector_material)
+
+ # outer cylinder
+ 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, detector_material, vacuum, black_surface, 0xff0000ff))
+
+ lbne.pmtids = []
+
+ # construct the barrel
+ for i in range(pmts_per_string):
+ for j in range(nstrings):
+ rotation = make_rotation_matrix(j*2*np.pi/nstrings, (0,0,1))
+ displacement = rotate((0,-radius,-height/2+i*height/(pmts_per_string-1)), j*2*np.pi/nstrings, (0,0,1))
+ lbne.pmtids.append(lbne.add_solid(pmt, rotation, displacement))
+
+ # construct the top endcap
+ for x, y in np.array(tuple(product(\
+ np.arange(-radius+0.075, radius, endcap_spacing),
+ np.arange(-radius+0.075, radius, endcap_spacing)))):
+ if np.sqrt(x**2 + y**2) < radius - endcap_spacing/2:
+ rotation = make_rotation_matrix(+np.pi/2, (1,0,0))
+ displacement = (x,y,+height/2+height/(pmts_per_string-1)/2)
+ lbne.pmtids.append(lbne.add_solid(pmt, rotation, displacement))
+
+ # construct the bottom endcap
+ for x, y in np.array(tuple(product(\
+ np.arange(-radius+0.075, radius, endcap_spacing),
+ np.arange(-radius+0.075, radius, endcap_spacing)))):
+ if np.sqrt(x**2 + y**2) < radius - endcap_spacing/2:
+ rotation = make_rotation_matrix(-np.pi/2, (1,0,0))
+ displacement = (x,y,-height/2-height/(pmts_per_string-1)/2)
+ lbne.pmtids.append(lbne.add_solid(pmt, rotation, displacement))
+
+ return lbne
diff --git a/chroma/detectors/miniclean.py b/chroma/detectors/miniclean.py
new file mode 100644
index 0000000..92dd019
--- /dev/null
+++ b/chroma/detectors/miniclean.py
@@ -0,0 +1,80 @@
+import numpy as np
+import numpy.linalg
+import math
+from chroma.make import linear_extrude, sphere
+from chroma.geometry import *
+from chroma.optics import *
+from chroma.transform import rotate, make_rotation_matrix
+from chroma.itertoolset import grouper
+import os
+
+
+dir = os.path.split(os.path.realpath(__file__))[0]
+
+def read_polygons(filename):
+ polygons = {}
+ with open(filename) as f:
+ for line in f:
+ parts = line.split()
+ idnum = int(parts[0])
+ npoints = int(parts[1])
+ points = np.zeros(shape=(npoints,2), dtype=np.float32)
+ for i, (x,y) in enumerate(grouper(2, parts[2:])):
+ points[i] = [float(x), float(y)]
+ polygons[idnum] = points
+ return polygons
+
+def read_cassettes(filename):
+ cassettes = []
+ with open(filename) as f:
+ for line in f:
+ parts = line.split()
+ cassette_type = int(parts[0])
+ rotation = np.transpose(np.array(map(float, parts[1:10]), dtype=np.float32).reshape((3,3)))
+ displacement = np.array(map(float, parts[10:13]), dtype=np.float32)
+
+ cassettes.append({'type' : cassette_type, 'rotation' : rotation,
+ 'displacement' : displacement})
+
+ return cassettes
+
+def build_miniclean(real_av=False):
+ geo = Geometry()
+
+ simple_iv = sphere(0.818)
+ geo.add_solid(Solid(simple_iv, liquid_argon, vacuum, color=0xffFF0000))
+
+ polygons = read_polygons(os.path.join(dir, 'miniclean_polygons.txt'))
+
+ height = 0.30
+ polygon_types = {}
+ for polygon_id, polygon_points in polygons.items():
+ mesh = linear_extrude(polygon_points[::-1,0]/1000.0,
+ polygon_points[::-1,1]/1000.0,
+ height=height,
+ center=[0,0,height/2])
+ colors = np.zeros(len(mesh.triangles), dtype=np.uint32)
+ colors.fill(0x03CCCCFF)
+ # Color the faces on one end
+ triangles = mesh.assemble(group=True)
+ triangle_centroids = triangles.mean(axis=1)
+ face = triangle_centroids[:,2] < 0.1
+ colors[face] = 0xffffff
+
+ polygon_types[polygon_id] = (mesh, colors)
+
+ cassettes = read_cassettes(os.path.join(dir, 'miniclean_cassettes.txt'))
+
+ geo.pmtids = []
+ geo.pmt_id_map = {}
+ for i, cassette in enumerate(cassettes):
+ polygon_mesh, polygon_colors = polygon_types[cassette['type']]
+ solid = Solid(polygon_mesh, liquid_argon, liquid_argon, surface=shiny_surface,
+ color=polygon_colors)
+
+ chroma_id = geo.add_solid(solid, cassette['rotation'],
+ cassette['displacement']/1000.0)
+ geo.pmt_id_map[chroma_id] = i
+ geo.pmtids.append(chroma_id)
+
+ return geo
diff --git a/chroma/detectors/miniclean_cassettes.txt b/chroma/detectors/miniclean_cassettes.txt
new file mode 100644
index 0000000..a5e59f2
--- /dev/null
+++ b/chroma/detectors/miniclean_cassettes.txt
@@ -0,0 +1,92 @@
+1 1.000000 -0.000000 0.000000 0.000000 1.000000 0.000000 -0.000000 -0.000000 1.000000 0.000000 0.000000 435.000000
+1 0.361804 0.262866 -0.894427 -0.587785 0.809017 0.000000 0.723607 0.525731 0.447214 314.768956 228.692931 194.538037
+1 -0.138197 0.425326 -0.894427 -0.951057 -0.309017 0.000000 -0.276393 0.850651 0.447214 -120.230916 370.033081 194.538032
+1 -0.447214 0.000000 -0.894427 -0.000000 -1.000000 0.000000 -0.894427 0.000000 0.447214 -389.075740 0.000000 194.538090
+1 -0.138197 -0.425326 -0.894427 0.951057 -0.309017 -0.000000 -0.276393 -0.850651 0.447214 -120.230916 -370.033081 194.538032
+1 0.361804 -0.262866 -0.894427 0.587785 0.809017 -0.000000 0.723607 -0.525731 0.447214 314.768956 -228.692931 194.538037
+1 0.447214 0.000000 0.894427 0.000000 -1.000000 -0.000000 0.894427 0.000000 -0.447214 389.075740 0.000000 -194.538090
+1 0.138197 0.425326 0.894427 0.951057 -0.309017 0.000000 0.276393 0.850651 -0.447214 120.230916 370.033081 -194.538032
+1 -0.361804 0.262866 0.894427 0.587785 0.809017 -0.000000 -0.723607 0.525731 -0.447214 -314.768956 228.692931 -194.538037
+1 -0.361804 -0.262866 0.894427 -0.587785 0.809017 0.000000 -0.723607 -0.525731 -0.447214 -314.768956 -228.692931 -194.538037
+1 0.138197 -0.425326 0.894427 -0.951057 -0.309017 0.000000 0.276393 -0.850651 -0.447214 120.230916 -370.033081 -194.538032
+1 -1.000000 -0.000000 0.000000 -0.000000 1.000000 -0.000000 0.000000 -0.000000 -1.000000 0.000000 0.000000 -435.000000
+2 0.794654 -0.000000 -0.607062 0.000000 1.000000 0.000000 0.607062 -0.000000 0.794654 264.072061 0.000000 345.674625
+2 0.245561 0.755761 -0.607062 -0.951057 0.309016 0.000000 0.187592 0.577350 0.794654 81.602569 251.147409 345.674702
+2 -0.642889 0.467086 -0.607062 -0.587786 -0.809017 0.000000 -0.491123 0.356822 0.794655 -213.638636 155.217674 345.674713
+2 -0.642889 -0.467086 -0.607062 0.587786 -0.809017 0.000000 -0.491123 -0.356822 0.794655 -213.638636 -155.217674 345.674713
+2 0.245561 -0.755761 -0.607062 0.951057 0.309016 0.000000 0.187592 -0.577350 0.794654 81.602569 -251.147409 345.674702
+2 0.187592 -0.000000 -0.982247 0.000000 1.000000 -0.000000 0.982247 -0.000000 0.187592 427.277460 0.000000 81.602523
+2 0.057969 0.178411 -0.982247 -0.951056 0.309017 -0.000000 0.303531 0.934172 0.187592 132.036041 406.364992 81.602557
+2 -0.151765 0.110264 -0.982247 -0.587785 -0.809017 -0.000000 -0.794654 0.577350 0.187592 -345.674702 251.147409 81.602569
+2 -0.151765 -0.110264 -0.982247 0.587785 -0.809017 0.000000 -0.794654 -0.577350 0.187592 -345.674702 -251.147409 81.602569
+2 0.057969 -0.178411 -0.982247 0.951056 0.309017 0.000000 0.303531 -0.934172 0.187592 132.036041 -406.364992 81.602557
+2 -0.151765 -0.110264 -0.982247 -0.587785 0.809017 -0.000000 0.794654 0.577350 -0.187592 345.674702 251.147409 -81.602569
+2 0.057969 -0.178411 -0.982247 -0.951056 -0.309017 -0.000000 -0.303531 0.934172 -0.187592 -132.036041 406.364992 -81.602557
+2 0.187592 0.000000 -0.982247 -0.000000 -1.000000 -0.000000 -0.982247 0.000000 -0.187592 -427.277460 0.000000 -81.602523
+2 0.057969 0.178411 -0.982247 0.951056 -0.309017 0.000000 -0.303531 -0.934172 -0.187592 -132.036041 -406.364992 -81.602557
+2 -0.151765 0.110264 -0.982247 0.587785 0.809017 0.000000 0.794654 -0.577350 -0.187592 345.674702 -251.147409 -81.602569
+2 -0.642889 -0.467086 -0.607062 -0.587786 0.809017 0.000000 0.491123 0.356822 -0.794655 213.638636 155.217674 -345.674713
+2 0.245561 -0.755761 -0.607062 -0.951057 -0.309016 -0.000000 -0.187592 0.577350 -0.794654 -81.602569 251.147409 -345.674702
+2 0.794654 0.000000 -0.607062 -0.000000 -1.000000 -0.000000 -0.607062 0.000000 -0.794654 -264.072061 0.000000 -345.674625
+2 0.245561 0.755761 -0.607062 0.951057 -0.309016 -0.000000 -0.187592 -0.577350 -0.794654 -81.602569 -251.147409 -345.674702
+2 -0.642889 0.467086 -0.607062 0.587786 0.809017 -0.000000 0.491123 -0.356822 -0.794655 213.638636 -155.217674 -345.674713
+3 0.759856 0.552068 -0.343278 -0.587785 0.809017 0.000000 0.277718 0.201774 0.939234 120.807298 87.771665 408.566679
+3 -0.290240 0.893264 -0.343278 -0.951056 -0.309018 0.000000 -0.106079 0.326477 0.939234 -46.144352 142.017454 408.566692
+3 -0.939234 0.000000 -0.343279 -0.000000 -1.000000 0.000000 -0.343279 0.000000 0.939234 -149.326291 0.000000 408.566590
+3 -0.290240 -0.893264 -0.343278 0.951056 -0.309018 0.000000 -0.106079 -0.326477 0.939234 -46.144352 -142.017454 408.566692
+3 0.759856 -0.552068 -0.343278 0.587785 0.809017 0.000000 0.277718 -0.201774 0.939234 120.807298 -87.771665 408.566679
+3 -0.588217 -0.427365 0.686557 0.587785 -0.809017 -0.000000 0.555436 0.403548 0.727076 241.614708 175.543411 316.278111
+3 0.224679 -0.691490 0.686557 0.951056 0.309017 -0.000000 -0.212158 0.652955 0.727076 -92.288693 284.035318 316.277940
+3 0.727076 -0.000000 0.686557 0.000000 1.000000 0.000000 -0.686557 -0.000000 0.727076 -298.652292 0.000000 316.278056
+3 0.224679 0.691490 0.686557 -0.951056 0.309017 0.000000 -0.212158 -0.652955 0.727076 -92.288693 -284.035318 316.277940
+3 -0.588217 0.427365 0.686557 -0.587785 -0.809017 0.000000 0.555436 -0.403548 0.727076 241.614708 -175.543411 316.278111
+3 0.171639 -0.979432 0.106079 0.525731 -0.000000 -0.850651 0.833155 0.201774 0.514918 362.422317 87.771667 223.989282
+3 -0.878456 0.465900 0.106079 -0.162460 -0.500000 0.850651 0.449358 0.730026 0.514918 195.470612 317.561131 223.989214
+3 0.984535 -0.139422 0.106079 0.162460 0.500000 -0.850651 0.065560 0.854729 0.514918 28.518594 371.807049 223.989304
+3 -0.714555 -0.691490 0.106079 0.425325 -0.309017 0.850651 -0.555436 0.652955 0.514918 -241.614670 284.035427 223.989346
+3 0.436836 0.893264 0.106079 -0.425326 0.309017 -0.850651 -0.792636 0.326477 0.514918 -344.796720 142.017520 223.989388
+3 0.436836 -0.893264 0.106079 0.425326 0.309017 0.850651 -0.792636 -0.326477 0.514918 -344.796720 -142.017520 223.989388
+3 -0.714555 0.691490 0.106079 -0.425325 -0.309017 -0.850651 -0.555436 -0.652955 0.514918 -241.614670 -284.035427 223.989346
+3 0.984535 0.139422 0.106079 -0.162460 0.500000 0.850651 0.065560 -0.854729 0.514918 28.518594 -371.807049 223.989304
+3 -0.878456 -0.465900 0.106079 0.162460 -0.500000 -0.850651 0.449358 -0.730026 0.514918 195.470612 -317.561131 223.989214
+3 0.171639 0.979432 0.106079 -0.525731 -0.000000 0.850651 0.833155 -0.201774 0.514918 362.422317 -87.771667 223.989282
+3 0.351017 -0.427365 -0.833155 -0.262866 0.809017 -0.525731 0.898715 0.403548 0.171639 390.941108 175.543414 74.662977
+3 -0.297978 0.465899 -0.833155 -0.688191 0.500000 0.525731 0.661515 0.730026 0.171639 287.759023 317.561312 74.662963
+3 0.514918 0.201774 -0.833155 -0.850651 -0.000000 -0.525731 -0.106079 0.979432 0.171639 -46.144370 426.052975 74.662974
+3 -0.535177 -0.139423 -0.833155 -0.688191 -0.500000 0.525731 -0.489876 0.854729 0.171639 -213.096050 371.807095 74.662959
+3 -0.032780 0.552068 -0.833155 -0.262865 -0.809017 -0.525731 -0.964275 0.201774 0.171639 -419.459842 87.771736 74.663001
+3 -0.032780 -0.552068 -0.833155 0.262865 -0.809017 0.525731 -0.964275 -0.201774 0.171639 -419.459842 -87.771736 74.663001
+3 -0.535177 0.139423 -0.833155 0.688191 -0.500000 -0.525731 -0.489876 -0.854729 0.171639 -213.096050 -371.807095 74.662959
+3 0.514918 -0.201774 -0.833155 0.850651 -0.000000 0.525731 -0.106079 -0.979432 0.171639 -46.144370 -426.052975 74.662974
+3 -0.297978 -0.465899 -0.833155 0.688191 0.500000 -0.525731 0.661515 -0.730026 0.171639 287.759023 -317.561312 74.662963
+3 0.351017 0.427365 -0.833155 0.262866 0.809017 0.525731 0.898715 -0.403548 0.171639 390.941108 -175.543414 74.662977
+3 0.032780 0.552068 0.833155 0.262865 -0.809017 0.525731 0.964275 0.201774 -0.171639 419.459842 87.771736 -74.663001
+3 0.535177 -0.139423 0.833155 0.688191 -0.500000 -0.525731 0.489876 0.854729 -0.171639 213.096050 371.807095 -74.662959
+3 -0.514918 0.201774 0.833155 0.850651 -0.000000 0.525731 0.106079 0.979432 -0.171639 46.144370 426.052975 -74.662974
+3 0.297978 0.465899 0.833155 0.688191 0.500000 -0.525731 -0.661515 0.730026 -0.171639 -287.759023 317.561312 -74.662963
+3 -0.351017 -0.427365 0.833155 0.262866 0.809017 0.525731 -0.898715 0.403548 -0.171639 -390.941108 175.543414 -74.662977
+3 -0.351017 0.427365 0.833155 -0.262866 0.809017 -0.525731 -0.898715 -0.403548 -0.171639 -390.941108 -175.543414 -74.662977
+3 0.297978 -0.465899 0.833155 -0.688191 0.500000 0.525731 -0.661515 -0.730026 -0.171639 -287.759023 -317.561312 -74.662963
+3 -0.514918 -0.201774 0.833155 -0.850651 -0.000000 -0.525731 0.106079 -0.979432 -0.171639 46.144370 -426.052975 -74.662974
+3 0.535177 0.139423 0.833155 -0.688191 -0.500000 0.525731 0.489876 -0.854729 -0.171639 213.096050 -371.807095 -74.662959
+3 0.032780 -0.552068 0.833155 -0.262865 -0.809017 -0.525731 0.964275 -0.201774 -0.171639 419.459842 -87.771736 -74.663001
+3 -0.436836 0.893264 -0.106079 0.425326 0.309017 0.850651 0.792636 0.326477 -0.514918 344.796720 142.017520 -223.989388
+3 0.714555 -0.691490 -0.106079 -0.425325 -0.309017 -0.850651 0.555436 0.652955 -0.514918 241.614670 284.035427 -223.989346
+3 -0.984535 -0.139422 -0.106079 -0.162460 0.500000 0.850651 -0.065560 0.854729 -0.514918 -28.518594 371.807049 -223.989304
+3 0.878456 0.465900 -0.106079 0.162460 -0.500000 -0.850651 -0.449358 0.730026 -0.514918 -195.470612 317.561131 -223.989214
+3 -0.171639 -0.979432 -0.106079 -0.525731 -0.000000 0.850651 -0.833155 0.201774 -0.514918 -362.422317 87.771667 -223.989282
+3 -0.171639 0.979432 -0.106079 0.525731 -0.000000 -0.850651 -0.833155 -0.201774 -0.514918 -362.422317 -87.771667 -223.989282
+3 0.878456 -0.465900 -0.106079 -0.162460 -0.500000 0.850651 -0.449358 -0.730026 -0.514918 -195.470612 -317.561131 -223.989214
+3 -0.984535 0.139422 -0.106079 0.162460 0.500000 -0.850651 -0.065560 -0.854729 -0.514918 -28.518594 -371.807049 -223.989304
+3 0.714555 0.691490 -0.106079 0.425325 -0.309017 0.850651 0.555436 -0.652955 -0.514918 241.614670 -284.035427 -223.989346
+3 -0.436836 -0.893264 -0.106079 -0.425326 0.309017 -0.850651 0.792636 -0.326477 -0.514918 344.796720 -142.017520 -223.989388
+3 -0.727076 0.000000 -0.686557 0.000000 1.000000 -0.000000 0.686557 -0.000000 -0.727076 298.652292 0.000000 -316.278056
+3 -0.224679 -0.691490 -0.686557 -0.951056 0.309017 -0.000000 0.212158 0.652955 -0.727076 92.288693 284.035318 -316.277940
+3 0.588217 -0.427365 -0.686557 -0.587785 -0.809017 -0.000000 -0.555436 0.403548 -0.727076 -241.614708 175.543411 -316.278111
+3 0.588217 0.427365 -0.686557 0.587785 -0.809017 -0.000000 -0.555436 -0.403548 -0.727076 -241.614708 -175.543411 -316.278111
+3 -0.224679 0.691490 -0.686557 0.951056 0.309017 -0.000000 0.212158 -0.652955 -0.727076 92.288693 -284.035318 -316.277940
+3 0.939234 0.000000 0.343279 0.000000 -1.000000 -0.000000 0.343279 0.000000 -0.939234 149.326291 0.000000 -408.566590
+3 0.290240 0.893264 0.343278 0.951056 -0.309018 -0.000000 0.106079 0.326477 -0.939234 46.144352 142.017454 -408.566692
+3 -0.759856 0.552068 0.343278 0.587785 0.809017 -0.000000 -0.277718 0.201774 -0.939234 -120.807298 87.771665 -408.566679
+3 -0.759856 -0.552068 0.343278 -0.587785 0.809017 -0.000000 -0.277718 -0.201774 -0.939234 -120.807298 -87.771665 -408.566679
+3 0.290240 -0.893264 0.343278 -0.951056 -0.309018 -0.000000 0.106079 -0.326477 -0.939234 46.144352 -142.017454 -408.566692
diff --git a/chroma/detectors/miniclean_polygons.txt b/chroma/detectors/miniclean_polygons.txt
new file mode 100644
index 0000000..594ed7d
--- /dev/null
+++ b/chroma/detectors/miniclean_polygons.txt
@@ -0,0 +1,3 @@
+1 5 -66.925194 48.624001 25.563150 78.675285 82.724091 0.000000 25.563150 -78.675285 -66.925194 -48.624001
+3 6 -84.296997 48.624001 1.690830 107.301506 87.678658 61.878311 87.678658 -61.878311 1.690830 -107.301506 -84.296997 -48.624001
+2 6 -97.248001 0.000000 -48.624001 84.219238 48.624001 84.219238 97.248001 0.000000 48.624001 -84.219238 -48.624001 -84.219238
diff --git a/chroma/detectors/sno.py b/chroma/detectors/sno.py
new file mode 100644
index 0000000..d5c9ce9
--- /dev/null
+++ b/chroma/detectors/sno.py
@@ -0,0 +1,133 @@
+import numpy as np
+import numpy.linalg
+import math
+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):
+ '''Compute the 2D coordinates of the profile of one side of a
+ SNO-style acrylic vessel. The center of the sphere is at (0,0), with
+ the neck extending along the positive y direction.
+
+ sphere_radius: Radius of spherical part of profile
+ neck_radius: Radius of neck part
+ neck_top: y coordinate of top of neck
+ nsteps: number of points around the circumference of the sphere
+
+ Returns: Tuple of x and y coordinate numpy arrays.
+ '''
+ if neck_radius >= sphere_radius:
+ raise ValueError('neck_radius must be less than sphere_radius')
+
+ intersect_height = (sphere_radius**2 - neck_radius**2)**0.5
+ max_angle = math.atan2(intersect_height, neck_radius)
+
+ if neck_top < intersect_height:
+ raise ValueError('neck_top must be greater than the y-value where the sphere and cylinder intersect')
+
+ # Start with point at bottom
+ angles = np.linspace(-math.pi/2, max_angle, nsteps)
+ x = list(np.cos(angles) * sphere_radius)
+ y = list(np.sin(angles) * sphere_radius)
+ x[0] = 0.0 # Round-off error might make cos(-pi/2) not exactly zero
+
+ # Neck intersection point
+ x.append(neck_radius)
+ y.append(intersect_height)
+
+ # Top of neck
+ x.append(neck_radius)
+ y.append(neck_top)
+
+ # Top of neck on axis
+ x.append(0.0)
+ y.append(neck_top)
+
+ return x, y
+
+##### SNO Parts
+
+nsteps = 40
+av_outside_profile = sno_vessel(sphere_radius=6.0604, neck_radius=0.79375,
+ neck_top=10.50, nsteps=nsteps)
+# For simplicity, cap the top of the AV with acrylic
+av_inside_profile = sno_vessel(sphere_radius=6.0053, neck_radius=0.72898,
+ neck_top=10.00, nsteps=nsteps)
+
+av_outside_mesh = rotate_extrude(av_outside_profile[0], av_outside_profile[1],
+ nsteps)
+av_outside_mesh.vertices = rotate(av_outside_mesh.vertices, np.pi/2, (-1,0,0))
+
+av_inside_mesh = rotate_extrude(av_inside_profile[0], av_inside_profile[1],
+ nsteps)
+av_inside_mesh.vertices = rotate(av_inside_mesh.vertices, np.pi/2, (-1,0,0))
+
+dir = os.path.split(os.path.realpath(__file__))[0]
+
+def build_sno(real_av=False):
+ import h5py
+ pmtinfo = h5py.File(dir+'/sno_pmt_info.hdf5')
+
+ pmt = build_8inch_pmt_with_lc()
+
+
+ if real_av:
+ geo = Geometry(water)
+ real_av_mesh = mesh_from_stl(dir+'/sno_av_ascii.stl.bz2')
+ real_av_mesh.vertices *= 0.0254 # inch -> meter
+ geo.add_solid(Solid(real_av_mesh, glass, water, color=0xBBAAAAFF))
+ else:
+ geo = Geometry(water)
+ geo.add_solid(Solid(av_outside_mesh, acrylic_sno, water,
+ color=0xBBFFFFFF))
+ geo.add_solid(Solid(av_inside_mesh, water, acrylic_sno,
+ color=0xBB0000FF))
+ geo.pmtids = []
+
+ snoman_id_dict = {}
+
+ pmt_offset = 122.0 - 2 * 0.01# max bucket height - 2 * facegap (mm)
+
+ for position, direction, idnum, pmt_type in zip(pmtinfo['pos'], pmtinfo['dir'],
+ pmtinfo['snoman_id'],
+ pmtinfo['pmt_type']):
+
+ # PMT type codes:
+ # 1 = normal; 2 = OWL; 3 = Low Gain; 4 = BUTT; 5 = Neck
+ # 6 = Calib channel; 10 = spare; 11 = invalid
+ if pmt_type != 1: # All the other PMTs have nonsense directions
+ continue
+
+
+ # Flip and renormalize
+ direction *= -1.0/numpy.linalg.norm(direction)
+
+ # Orient PMT that starts facing Y axis
+ y_axis = np.array((0.0,1.0,0.0))
+ axis = np.cross(direction, y_axis)
+ angle = np.arccos(np.dot(y_axis, direction))
+ rotation = make_rotation_matrix(angle, axis)
+
+ # Values in database are for front face of concentrator.
+ # need to shift so position is for equator of PMT
+ if pmt_type == 1:
+ displacement = position - direction * pmt_offset
+ displacement /= 1000.0 # mm -> m
+ chroma_id = geo.add_solid(pmt, rotation, displacement)
+ snoman_id_dict[chroma_id] = idnum
+ geo.pmtids.append(chroma_id)
+
+ # Convert dict to numpy array for fast array remapping later
+ chroma_ids = np.array(snoman_id_dict.keys())
+ snoman_ids = np.array(snoman_id_dict.values())
+ snoman_id_map = np.zeros(max(chroma_ids)+1) - 1 # Fill with -1 everywhere
+ snoman_id_map[chroma_ids] = snoman_ids
+
+ geo.snoman_id_map = snoman_id_map
+
+ return geo
diff --git a/chroma/detectors/sno_av_ascii.stl.bz2 b/chroma/detectors/sno_av_ascii.stl.bz2
new file mode 100644
index 0000000..1298a60
--- /dev/null
+++ b/chroma/detectors/sno_av_ascii.stl.bz2
Binary files differ
diff --git a/chroma/detectors/sno_pmt_info.hdf5 b/chroma/detectors/sno_pmt_info.hdf5
new file mode 100644
index 0000000..1358189
--- /dev/null
+++ b/chroma/detectors/sno_pmt_info.hdf5
Binary files differ