示例#1
0
 def test_detx_v5(self):
     det = Detector(filename=data_path("detx/detx_v5.detx"))
     assert np.allclose([464.4, 564.7, 190.583],
                        det.dom_positions[808956908],
                        atol=1e-2)
     assert np.allclose([464.4, 564.7, 95.389],
                        det.dom_positions[808981864],
                        atol=1e-2)
     assert det.n_doms == 114
     assert det.det_id == 49
     assert det.n_pmts_per_dom == 31
     assert det.n_dus == 6
     assert np.allclose(
         det.doms[808981864],
         [
             1.0000000e01,
             8.0000000e00,
             3.1000000e01,
             4.6440000e02,
             5.6470000e02,
             9.5389000e01,
             9.9995400e-01,
             -7.8470000e-03,
             3.9110000e-03,
             4.0080000e-03,
             0.0000000e00,
             3.7861343e04,
         ],
         atol=1e-2,
     )
     assert np.allclose(
         np.array([
             [484.6, 564.65],
             [464.4, 564.7],
             [442.5, 567.45],
             [474.15, 583.45],
             [454.2, 583.0],
             [431.1, 583.5],
         ]),
         det.xy_positions,
     )
     assert np.allclose(
         [
             3,
             0.73205,
             0.614161,
             0.29479,
             808981864,
             10,
             8,
             13367,
             464.546,
             564.823,
             95.448,
             0,
             207862.961,
         ],
         list(det.get_pmt(808981864, 3)),
     )
示例#2
0
    def test_detx_format_comments(self):
        det = Detector(filename=data_path("detx/detx_v1.detx"))
        assert len(det.comments) == 0

        det = Detector(filename=data_path("detx/detx_v2.detx"))
        assert len(det.comments) == 0

        det = Detector(filename=data_path("detx/detx_v3.detx"))
        assert len(det.comments) == 2
        assert " a comment line" == det.comments[0]
        assert " another comment line starting with '#'" == det.comments[1]
示例#3
0
 def test_detx_v4(self):
     det = Detector(filename=data_path("detx/detx_v4.detx"))
     assert np.allclose([119.6, -12.2, 192.77],
                        det.dom_positions[808956908],
                        atol=1e-2)
     assert np.allclose([119.6, -12.2, 97.44],
                        det.dom_positions[808981864],
                        atol=1e-2)
     assert det.n_doms == 90
     assert det.det_id == 44
     assert det.n_pmts_per_dom == 31
     assert det.n_dus == 5
     assert np.allclose(
         det.doms[808945480],
         [
             1,
             5,
             31,
             86.500,
             9.100,
             66.821,
             1.000000,
             0.000000,
             0.000000,
             0.000000,
             0.000,
         ],
         atol=1e-2,
     )
     assert np.allclose(
         np.array([[86.5, 9.1], [86.6, 6.6], [109.6, 5.9], [97.8, -9.6],
                   [119.6, -12.2]]),
         det.xy_positions,
     )
     assert np.allclose(
         [
             3,
             0.844,
             0.449,
             0.295,
             808981864,
             5,
             8,
             13367,
             119.768,
             -12.11,
             97.5,
             0,
             207863.242,
         ],
         list(det.get_pmt(808981864, 3)),
     )
示例#4
0
    def test_dom_table_with_another_detx(self):
        det = Detector()
        det._det_file = EXAMPLE_DETX_RADIAL
        det._parse_doms()

        dt = det.dom_table
        assert 4 == len(dt)
        assert np.allclose([1, 2, 3, 4], dt.dom_id)
        assert np.allclose([1, 1, 1, 2], dt.du)
        assert np.allclose([1, 2, 3, 1], dt.floor)
        assert np.allclose([0, 0, 0, 0], dt.pos_x)
        assert np.allclose([0, 0, 0, 0], dt.pos_y)
        assert np.allclose([0, 0, 0, 0], dt.pos_z)
示例#5
0
    def test_dom_table_with_another_detx(self):
        det = Detector()
        det._det_file = EXAMPLE_DETX_RADIAL
        det._parse()

        dt = det.dom_table
        assert 4 == len(dt)
        assert np.allclose([1, 2, 3, 4], dt.dom_id)
        assert np.allclose([1, 1, 1, 2], dt.du)
        assert np.allclose([1, 2, 3, 1], dt.floor)
        assert np.allclose([0, 0, 0, 0], dt.pos_x)
        assert np.allclose([0, 0, 0, 0], dt.pos_y)
        assert np.allclose([0, 0, 0, 0], dt.pos_z)
示例#6
0
    def __init__(self, width=800, height=600, x=112, y=84):

        self.init_opengl(width=width, height=height, x=x, y=y)

        print("OpenGL Version: {0}".format(glGetString(GL_VERSION)))
        self.clock = Clock(speed=100)
        self.timer = Clock(snooze_interval=1/30)
        self.frame_index = 0
        self.event_index = 0
        self.is_recording = False

        VERTEX_SHADER = compileShader("""
        void main() {
            gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
        }""", GL_VERTEX_SHADER)
        FRAGMENT_SHADER = compileShader("""
        void main() {
            gl_FragColor = vec4(0.8, 0.8, 0.8, 1);
        }""", GL_FRAGMENT_SHADER)

        self.shader = compileProgram(VERTEX_SHADER, FRAGMENT_SHADER)

        self.coordsys = vbo.VBO(
            np.array([
                [-1, 0, 0],
                [1, 0, 0],
                [0, -1, 0],
                [0, 1, 0],
                [0, 0, -1],
                [0, 0, 1]
                ], 'f')
            )

        self.blob = None
        self.objects = []
        self.shaded_objects = []

        self.mouse_x = None
        self.mouse_y = None

        self.show_help = False
        self._help_string = None
        self.show_info = False

        self.spectrum = None

        self.detector = Detector('/Users/tamasgal/Data/KM3NeT/Detector/km3net_jul13_90m.detx')
        self.dom_positions = np.array([tuple(pos) for pos in self.detector.dom_positions], 'f')
        self.min_z = min([z for x, y, z in self.dom_positions])
        self.max_z = max([z for x, y, z in self.dom_positions])
        camera.target = Position((0, 0, (self.max_z - self.min_z) / 2))
        self.dom_positions_vbo = vbo.VBO(self.dom_positions)

        self.pump = EvtPump(filename='/Users/tamasgal/Data/KM3NeT/Luigi/nueCC.evt')
        self.load_blob(0)

        self.clock.reset()
        self.timer.reset()
        glutMainLoop()
示例#7
0
 def test_detx_format_version_1(self):
     det = Detector(filename=data_path("detx/detx_v1.detx"))
     assert 2 == det.n_dus
     assert 6 == det.n_doms
     assert 3 == det.n_pmts_per_dom
     assert 1 == det.version
     self.assertListEqual([1.1, 1.2, 1.3], list(det.pmts.pos[0]))
     self.assertListEqual([3.4, 3.5, 3.6], list(det.pmts.pos[7]))
     self.assertListEqual([23.4, 23.5, 23.6], list(det.pmts.pos[16]))
示例#8
0
文件: calib.py 项目: KM3NeT/km3pipe
    def configure(self):
        self._should_apply = self.get("apply", default=True)
        self.filename = self.get("filename")
        self.det_id = self.get("det_id")
        self.run = self.get("run")
        self.t0set = self.get("t0set")
        self.calibset = self.get("calibset")
        self.detector = self.get("detector")
        self.key = self.get("key", default="Hits")
        self.outkey = self.get("outkey", default="CalibHits")
        self.key_mc = self.get("key_mc", default="McHits")
        self.outkey_mc = self.get("outkey_mc", default="CalibMcHits")
        self._pos_dom_channel = None
        self._dir_dom_channel = None
        self._t0_dom_channel = None
        self._pos_pmt_id = None
        self._dir_pmt_id = None
        self._t0_pmt_id = None
        self._lookup_tables = None  # for Numba

        if self.det_id and self.run:
            self.cprint(
                "Grabbing the calibration for Det ID {} and run {}".format(
                    self.det_id, self.run))
            raw_detx = km3db.tools.detx_for_run(self.det_id, self.run)
            self.detector = Detector(string=raw_detx)
            self._create_dom_channel_lookup()
            self._create_pmt_id_lookup()
            return

        if self.filename or self.det_id:
            if self.filename is not None:
                self.detector = Detector(filename=self.filename)
            if self.det_id:
                self.detector = Detector(det_id=self.det_id,
                                         t0set=self.t0set,
                                         calibset=self.calibset)

        if self.detector is not None:
            self.log.debug("Creating lookup tables")
            self._create_dom_channel_lookup()
            self._create_pmt_id_lookup()
        else:
            self.log.critical("No detector information loaded.")
示例#9
0
 def test_jdetectordb_output_with_detx_v3(self):
     det = Detector(
         data_path(
             "detx/D_ORCA006_t.A02181836.p.A02181837.r.A02182001.detx"))
     assert det.utm_info is not None
     assert det.utm_info.ellipsoid == "WGS84"
     assert det.utm_info.grid == "32N"
     assert det.utm_info.easting == 256500.0
     assert det.utm_info.northing == 4743000.0
     assert det.utm_info.z == -2440.0
示例#10
0
    def test_ascii_with_mixed_dom_ids(self):
        detx_string = "\n".join((
            "1 3",
            "8 1 1 3",
            " 1 1.1 1.2 1.3 1.1 2.1 3.1 10.0",
            " 2 1.4 1.5 1.6 4.1 5.1 6.1 20.0",
            " 3 1.7 1.8 1.9 7.1 8.1 9.1 30.0",
            "4 1 2 3",
            " 4 2.1 2.2 2.3 1.2 2.2 3.2 40.0",
            " 5 2.4 2.5 2.6 4.2 5.2 6.2 50.0",
            " 6 2.7 2.8 2.9 7.2 8.2 9.2 60.0",
            "9 1 3 3",
            " 7 3.1 3.2 3.3 1.3 2.3 3.3 70.0",
            " 8 3.4 3.5 3.6 4.3 5.3 6.3 80.0",
            " 9 3.7 3.8 3.9 7.3 8.3 9.3 90.0\n",
        ))
        detx_fobj = StringIO(detx_string)

        self.det = Detector()
        self.det._det_file = detx_fobj
        self.det._parse()
        assert detx_string == self.det.ascii
示例#11
0
    def setUp(self):
        self.track = {
            "pos_x": 1.7524502152598151,
            "pos_y": 39.06202405657308,
            "pos_z": 130.44049806891948,
            "dir_x": 0.028617421257374293,
            "dir_y": -0.489704257367248,
            "dir_z": -0.8714188335794505,
        }

        self.det = Detector(data_path("detx/detx_v3.detx"))

        pd = km3pipe.extras.pandas()

        self.DU = pd.DataFrame(self.det.dom_table).mean()
示例#12
0
 def test_rotate_dom_set_by_step_by_360_degrees(self):
     det = Detector()
     det._det_file = EXAMPLE_DETX_RADIAL
     det._parse()
     dom_id = 1
     channel_id = 0
     pmt_dir = det.pmts[det.pmts.dom_id == dom_id].dir[channel_id].copy()
     pmt_pos = det.pmts[det.pmts.dom_id == dom_id].pos[channel_id].copy()
     for i in range(36):
         det.rotate_dom_by_yaw(dom_id, 10)
     pmt_dir_rot = det.pmts[det.pmts.dom_id == dom_id].dir[channel_id]
     assert np.allclose(pmt_dir, pmt_dir_rot)
     pmt_pos_rot = det.pmts[det.pmts.dom_id == dom_id].pos[channel_id]
     assert np.allclose(pmt_pos, pmt_pos_rot)
示例#13
0
 def test_detx_format_version_3_with_whitespace(self):
     det = Detector(filename=data_path("detx/detx_v3_whitespace.detx"))
     assert 2 == det.n_dus
     assert 6 == det.n_doms
     assert 3 == det.n_pmts_per_dom
     assert 256500.0 == det.utm_info.easting
     assert 4743000.0 == det.utm_info.northing
     assert "WGS84" == det.utm_info.ellipsoid
     assert "32N" == det.utm_info.grid
     assert -2425.0 == det.utm_info.z
     assert 1500000000.1 == det.valid_from
     assert 9999999999.0 == det.valid_until
     assert 3 == det.version
     self.assertListEqual([1.1, 1.2, 1.3], list(det.pmts.pos[0]))
     self.assertListEqual([3.4, 3.5, 3.6], list(det.pmts.pos[7]))
     self.assertListEqual([23.4, 23.5, 23.6], list(det.pmts.pos[16]))
示例#14
0
 def test_rotate_dom_by_yaw(self):
     det = Detector()
     det._det_file = EXAMPLE_DETX_RADIAL
     det._parse()
     # here, only one PMT is checked
     dom_id = 1
     heading = 23
     channel_id = 0
     pmt_dir = det.pmts[det.pmts.dom_id == dom_id].dir[channel_id].copy()
     pmt_dir_rot = qrot_yaw(pmt_dir, heading)
     det.rotate_dom_by_yaw(dom_id, heading)
     assert np.allclose(pmt_dir_rot,
                        det.pmts[det.pmts.dom_id == dom_id].dir[channel_id])
     assert np.allclose(
         [0.92050485, 0.39073113, 0],
         det.pmts[det.pmts.dom_id == dom_id].pos[channel_id],
     )
示例#15
0
 def test_rotate_du_by_yaw_step_by_step_360_degrees(self):
     det = Detector()
     det._det_file = EXAMPLE_DETX_RADIAL
     det._parse()
     du = 2
     pmt_dir = det.pmts[det.pmts.du == du].dir.copy()
     pmt_pos = det.pmts[det.pmts.du == du].pos.copy()
     pmt_dir_other_dus = det.pmts[det.pmts.du != du].dir.copy()
     pmt_pos_other_dus = det.pmts[det.pmts.du != du].pos.copy()
     for i in range(36):
         det.rotate_du_by_yaw(du, 10)
     pmt_dir_rot = det.pmts[det.pmts.du == du].dir
     pmt_pos_rot = det.pmts[det.pmts.du == du].pos
     assert np.allclose(pmt_dir, pmt_dir_rot)
     assert np.allclose(pmt_pos, pmt_pos_rot)
     assert np.allclose(pmt_dir_other_dus, det.pmts[det.pmts.du != du].dir)
     assert np.allclose(pmt_pos_other_dus, det.pmts[det.pmts.du != du].pos)
示例#16
0
 def test_init_from_string(self):
     detx_string = "\n".join((
         "1 3",
         "8 1 1 3",
         " 1 1.1 1.2 1.3 1.1 2.1 3.1 10.0",
         " 2 1.4 1.5 1.6 4.1 5.1 6.1 20.0",
         " 3 1.7 1.8 1.9 7.1 8.1 9.1 30.0",
         "4 1 2 3",
         " 4 2.1 2.2 2.3 1.2 2.2 3.2 40.0",
         " 5 2.4 2.5 2.6 4.2 5.2 6.2 50.0",
         " 6 2.7 2.8 2.9 7.2 8.2 9.2 60.0",
         "9 1 3 3",
         " 7 3.1 3.2 3.3 1.3 2.3 3.3 70.0",
         " 8 3.4 3.5 3.6 4.3 5.3 6.3 80.0",
         " 9 3.7 3.8 3.9 7.3 8.3 9.3 90.0\n",
     ))
     det = Detector(string=detx_string)
     assert 1 == det.n_dus
     assert 3 == det.n_doms
示例#17
0
 def test_rotate_dom_set_by_step_by_360_degrees(self):
     det = Detector()
     det._det_file = EXAMPLE_DETX_RADIAL
     det._parse_doms()
     dom_id = 1
     channel_id = 0
     pmt_dir = det.pmts[det.pmts.dom_id == dom_id].dir[channel_id].copy()
     pmt_pos = det.pmts[det.pmts.dom_id == dom_id].pos[channel_id].copy()
     for i in range(36):
         det.rotate_dom_by_yaw(dom_id, 10)
     pmt_dir_rot = det.pmts[det.pmts.dom_id == dom_id].dir[channel_id]
     assert np.allclose(pmt_dir, pmt_dir_rot)
     pmt_pos_rot = det.pmts[det.pmts.dom_id == dom_id].pos[channel_id]
     assert np.allclose(pmt_pos, pmt_pos_rot)
示例#18
0
 def test_rotate_dom_by_yaw(self):
     det = Detector()
     det._det_file = EXAMPLE_DETX_RADIAL
     det._parse_doms()
     # here, only one PMT is checked
     dom_id = 1
     heading = 23
     channel_id = 0
     pmt_dir = det.pmts[det.pmts.dom_id == dom_id].dir[channel_id].copy()
     pmt_dir_rot = qrot_yaw(pmt_dir, heading)
     det.rotate_dom_by_yaw(dom_id, heading)
     assert np.allclose(
         pmt_dir_rot, det.pmts[det.pmts.dom_id == dom_id].dir[channel_id]
     )
     assert np.allclose([0.92050485, 0.39073113, 0],
                        det.pmts[det.pmts.dom_id == dom_id].pos[channel_id])
示例#19
0
 def test_rotate_du_by_yaw_step_by_step_360_degrees(self):
     det = Detector()
     det._det_file = EXAMPLE_DETX_RADIAL
     det._parse_doms()
     du = 2
     pmt_dir = det.pmts[det.pmts.du == du].dir.copy()
     pmt_pos = det.pmts[det.pmts.du == du].pos.copy()
     pmt_dir_other_dus = det.pmts[det.pmts.du != du].dir.copy()
     pmt_pos_other_dus = det.pmts[det.pmts.du != du].pos.copy()
     for i in range(36):
         det.rotate_du_by_yaw(du, 10)
     pmt_dir_rot = det.pmts[det.pmts.du == du].dir
     pmt_pos_rot = det.pmts[det.pmts.du == du].pos
     assert np.allclose(pmt_dir, pmt_dir_rot)
     assert np.allclose(pmt_pos, pmt_pos_rot)
     assert np.allclose(pmt_dir_other_dus, det.pmts[det.pmts.du != du].dir)
     assert np.allclose(pmt_pos_other_dus, det.pmts[det.pmts.du != du].pos)
示例#20
0
    def test_ascii_with_mixed_dom_ids(self):
        detx_string = "\n".join((
            "1 3",
            "8 1 1 3",
            " 1 1.1 1.2 1.3 1.1 2.1 3.1 10.0",
            " 2 1.4 1.5 1.6 4.1 5.1 6.1 20.0",
            " 3 1.7 1.8 1.9 7.1 8.1 9.1 30.0",
            "4 1 2 3",
            " 4 2.1 2.2 2.3 1.2 2.2 3.2 40.0",
            " 5 2.4 2.5 2.6 4.2 5.2 6.2 50.0",
            " 6 2.7 2.8 2.9 7.2 8.2 9.2 60.0",
            "9 1 3 3",
            " 7 3.1 3.2 3.3 1.3 2.3 3.3 70.0",
            " 8 3.4 3.5 3.6 4.3 5.3 6.3 80.0",
            " 9 3.7 3.8 3.9 7.3 8.3 9.3 90.0\n",
        ))
        detx_fobj = StringIO(detx_string)

        self.det = Detector()
        self.det._det_file = detx_fobj
        self.det._parse_header()
        self.det._parse_doms()
        assert detx_string == self.det.ascii
示例#21
0
 def setUp(self):
     self.det = Detector()
     self.det._det_file = EXAMPLE_DETX
示例#22
0
class RainbowAlga(object):
    def __init__(self, detector_file=None, event_file=None, min_tot=None,
                 skip_to_blob=0,
                 width=1000, height=700, x=50, y=50):
        self.camera = Camera()
        self.camera.is_rotating = True

        self.colourist = Colourist()

        current_path = os.path.dirname(os.path.abspath(__file__))

        if not detector_file:
            detector_file = os.path.join(current_path,
                            'data/km3net_jul13_90m_r1494_corrected.detx')

        self.load_logo()

        self.init_opengl(width=width, height=height, x=x, y=y)

        print("OpenGL Version: {0}".format(glGetString(GL_VERSION)))
        self.clock = Clock(speed=100)
        self.timer = Clock(snooze_interval=1/30)
        self.frame_index = 0
        self.event_index = skip_to_blob
        self.is_recording = False
        self.min_tot = min_tot

        VERTEX_SHADER = compileShader("""
        void main() {
            gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
        }""", GL_VERTEX_SHADER)
        FRAGMENT_SHADER = compileShader("""
        void main() {
            gl_FragColor = vec4(0.5, 0.5, 0.5, 1);
        }""", GL_FRAGMENT_SHADER)

        self.shader = compileProgram(VERTEX_SHADER, FRAGMENT_SHADER)


        self.blob = None
        self.objects = {}
        self.shaded_objects = []

        self.mouse_x = None
        self.mouse_y = None

        self.show_secondaries = True
        self.show_help = False
        self._help_string = None
        self.show_info = True

        self.spectrum = None
        self.current_spectrum = 'default'
        self.cmap = self.colourist.default_cmap
        self.min_hit_time = None
        self.max_hit_time = None

        self.detector = Detector(detector_file)
        dom_positions = self.detector.dom_positions
        min_z = min([z for x, y, z in dom_positions])
        max_z = max([z for x, y, z in dom_positions])
        z_shift = (max_z - min_z) / 2
        self.dom_positions = np.array([tuple(pos) for pos in dom_positions], 'f')
        self.camera.target = Position((0, 0, z_shift))
        self.dom_positions_vbo = vbo.VBO(self.dom_positions)

        if event_file:
            self.pump = EvtPump(filename=event_file)
            try:
                self.load_blob(skip_to_blob)
            except IndexError:
                print("Could not load blob at index {0}".format(skip_to_blob))
                print("Starting from the first one...")
                self.load_blob(0)
        else:
            print("No event file specified. Only the detector will be shown.")

        self.clock.reset()
        self.timer.reset()
        glutMainLoop()

    def load_logo(self):
        if self.colourist.print_mode:
            image = 'images/km3net_logo_print.bmp'
        else:
            image = 'images/km3net_logo.bmp'

        current_path = os.path.dirname(os.path.abspath(__file__))

        image_path = os.path.join(current_path, image)
        self.logo = Image.open(image_path)
        # Create a raw string from the image data - data will be unsigned bytes
        # RGBpad, no stride (0), and first line is top of image (-1)
        self.logo_bytes = self.logo.tobytes("raw", "RGB", 0, -1)

    def load_blob(self, index=0):
        print("Loading blob {0}...".format(index))
        blob = self.blob = self.pump.get_blob(index)

        self.objects = {}
        self.shaded_objects = []

        self.add_neutrino(blob)
        self.add_mc_tracks(blob)
        self.add_reco_tracks(blob)

        self.initialise_spectrum(blob, style=self.current_spectrum)

    def reload_blob(self):
        self.load_blob(self.event_index)

    def initialise_spectrum(self, blob, style="default"):

        if style == 'default':
            hits = self.extract_hits(blob)
            hits = self.remove_hidden_hits(hits)

            hit_times = []
            #step_size = int(len(hits) / 100) + 1
            for hit in hits:
                if hit.time > 0:
                    hit_times.append(hit.time)

            if len(hit_times) == 0:
                log.warn("No hits left after applying cuts.")
                return

            self.min_hit_time = min(hit_times)
            self.max_hit_time = max(hit_times)

            def spectrum(time, hit=None):
                min_time = min(hit_times)
                max_time = max(hit_times)
                diff = max_time - min_time
                one_percent = diff/100
                try:
                    progress = (time - min_time) / one_percent / 100
                except ZeroDivisionError:
                    progress = 0
                return tuple(self.cmap(progress))[:3]
            self.spectrum = spectrum

        if style == 'time_residuals':
            try:
                track_ins = blob['TrackIns']
            except KeyError:
                log.error("No tracks found to determine Cherenkov parameters!")
                self.current_spectrum = "default"
                return
            most_energetic_muon = max(track_ins, key=lambda t: t.E)
            if not pdg2name(most_energetic_muon.particle_type) in ['mu-', 'mu+']:
                log.error("No muon found to determine Cherenkov parameters!")
                self.current_spectrum = "default"
                return

            vertex_pos = most_energetic_muon.pos
            muon_dir = most_energetic_muon.dir

            hits = self.extract_hits(blob)
            hits = self.first_om_hits(hits)

            def cherenkov_time(pmt_pos):
                """Calculates Cherenkov arrival time in [ns]"""
                v = pmt_pos - vertex_pos
                l = v.dot(muon_dir)
                k = np.sqrt(v.dot(v) - l**2)
                v_g = constants.c_water_antares
                theta = constants.theta_cherenkov_water_antares
                t_cherenkov = 1/constants.c * (l - k/np.tan(theta)) + 1 /v_g * k/np.sin(theta)
                return t_cherenkov * 1e9

            self.min_hit_time = -100
            self.max_hit_time = 100

            def spectrum(time, hit=None):
                if hit:
                    pmt_pos = self.detector.pmt_with_id(hit.pmt_id).pos
                    if not hit.t_cherenkov:
                        t_cherenkov = cherenkov_time(pmt_pos)
                        hit.t_cherenkov = t_cherenkov
                        log.debug("Hit time: {0}, Expected: {1}, Time Residual: {2}"
                              .format(time, t_cherenkov, time - t_cherenkov))
                    time = time - hit.t_cherenkov

                diff = self.max_hit_time - self.min_hit_time
                one_percent = diff/100
                try:
                    progress = (time - self.min_hit_time) / one_percent / 100
                    if progress > 1:
                        progress = 1
                except ZeroDivisionError:
                    progress = 0
                return tuple(self.cmap(progress))[:3]
            self.spectrum = spectrum

    def toggle_spectrum(self):
        if self.current_spectrum == 'default':
            self.current_spectrum = 'time_residuals'
        else:
            self.current_spectrum = 'default'
        self.reload_blob()

    def remove_hidden_hits(self, hits):
        om_hit_map = {}
        for hit in hits:
            x, y, z = self.detector.pmt_with_id(hit.pmt_id).pos
            rb_hit = Hit(x, y, z, hit.time, hit.pmt_id, hit.id, hit.tot)
            om_hit_map.setdefault(self.detector.pmtid2omkey(hit.pmt_id)[:2],
                                  []).append(rb_hit)
        hits = []
        for om, om_hits in om_hit_map.iteritems():
            largest_hit = None
            for hit in om_hits:
                if largest_hit:
                    if hit.tot > largest_hit.tot:
                        hidden_hits = om_hits[:om_hits.index(hit)]
                        hit.replaces_hits = hidden_hits
                        hits.append(hit)
                        self.shaded_objects.append(hit)
                        largest_hit = hit
                else:
                    hits.append(hit)
                    self.shaded_objects.append(hit)
                    largest_hit = hit
        print(
            "Number of hits after removing hidden ones: {0}".format(len(hits)))
        return hits

    def first_om_hits(self, hits):
        om_hit_map = {}
        for hit in hits:
            if hit.time < 0:
                continue
            x, y, z = self.detector.pmt_with_id(hit.pmt_id).pos
            rb_hit = Hit(x, y, z, hit.time, hit.pmt_id, hit.id, hit.tot)
            om_hit_map.setdefault(self.detector.pmtid2omkey(hit.pmt_id)[:2],
                                  []).append(rb_hit)
        hits = []
        for om, om_hits in om_hit_map.iteritems():
            first_hit = om_hits[0]
            self.shaded_objects.append(first_hit)
            hits.append(first_hit)
        print(
            "Number of first OM hits: {0}".format(len(hits)))
        return hits

    def extract_hits(self, blob):
        hits = blob['EvtRawHits']
        print("Number of hits: {0}".format(len(hits)))
        if self.min_tot:
            hits = [hit for hit in blob['EvtRawHits'] if
                    hit.tot > self.min_tot]
            print("Number of hits after ToT={0} cut: {1}"
                  .format(self.min_tot, len(hits)))
        if not self.min_tot and len(hits) > 500:
            print("Warning: consider applying a ToT filter to reduce the "
                  "amount of hits, according to your graphic cards "
                  "performance!")
        hits.sort(key=lambda h: h.time)
        return hits

    def add_neutrino(self, blob):
        """Add the neutrino to the scene."""
        try:
            neutrino = blob['Neutrino']
        except KeyError:
            return
        print(neutrino)
        pos = Position((neutrino.pos.x, neutrino.pos.y, neutrino.pos.z))
        particle = Neutrino(pos.x, pos.y, pos.z,
                            neutrino.dir.x, neutrino.dir.y, neutrino.dir.z,
                            0)
        particle.color = (1.0, 0.0, 0.0)
        particle.line_width = 3
        self.objects.setdefault("neutrinos", []).append(particle)

    def add_mc_tracks(self, blob):
        """Find MC particles and add them to the objects to render."""
        try:
            track_ins = blob['TrackIns']
        except KeyError:
            return

        highest_energetic_track = max(track_ins, key=lambda t: t.E)
        highest_energy = highest_energetic_track.E
        for track in track_ins:
            if track.particle_type in (0, 22):
                # skip unknowns, photons
                continue
            if angle_between(highest_energetic_track.dir, track.dir) > 0.035:
                # TODO: make this realistic!
                # skip if angle too large
                continue
            if track.particle_type not in (-11, 11, -13, 13, -15, 15):
                # TODO: make this realistic!
                track.length = 200 * track.E / highest_energy
            particle = Particle(track.pos.x, track.pos.y, track.pos.z,
                                track.dir.x, track.dir.y, track.dir.z,
                                track.time, constants.c, self.colourist,
                                track.E, track.length)
            particle.hidden = not self.show_secondaries
            if track.id == highest_energetic_track.id:
                particle.color = (0.0, 1.0, 0.2)
                particle.line_width = 3
                particle.cherenkov_cone_enabled = True
                particle.hidden = False
            self.objects.setdefault("mc_tracks", []).append(particle)

    def add_reco_tracks(self, blob):
        """Find reco particles and add them to the objects to render."""
        try:
            track_fits = blob['TrackFits']
        except KeyError:
            return
        for track in track_fits:
            if not int(track.id) == 314:
                continue
            particle = ParticleFit(track.pos.x, track.pos.y, track.pos.z,
                                   track.dir.x, track.dir.y, track.dir.z,
                                   constants.c, track.ts, track.te)
            print("Found track fit: {0}".format(track))
            self.objects.setdefault("reco_tracks", []).append(particle)

    def toggle_secondaries(self):
        self.show_secondaries = not self.show_secondaries

        secondaries = self.objects["mc_tracks"]
        for secondary in secondaries:
            secondary.hidden = not self.show_secondaries

        highest_energetic = max(secondaries, key=lambda s: s.energy)
        if highest_energetic:
            highest_energetic.hidden = False


    def load_next_blob(self):
        try:
            self.load_blob(self.event_index + 1)
        except IndexError:
            return
        else:
            self.clock.reset()
            self.event_index += 1

    def load_previous_blob(self):
        try:
            self.load_blob(self.event_index - 1)
        except IndexError:
            return
        else:
            self.clock.reset()
            self.event_index -= 1


    def init_opengl(self, width, height, x, y):
        glutInit()
        glutInitWindowPosition(x, y)
        glutInitWindowSize(width, height)
        glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH | GLUT_MULTISAMPLE)
        glutCreateWindow("Rainbow Alga")
        glutDisplayFunc(self.render)
        glutIdleFunc(self.render)
        glutReshapeFunc(self.resize)

        glutMouseFunc(self.mouse)
        glutMotionFunc(self.drag)
        glutKeyboardFunc(self.keyboard)
        glutSpecialFunc(self.special_keyboard)

        glClearDepth(1.0)
        glClearColor(0.0, 0.0, 0.0, 0.0)
        glMatrixMode(GL_PROJECTION)
        glLoadIdentity()
        glFrustum(-1.0, 1.0, -1.0, 1.0, 1.0, 3000)
        glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT)


        # Lighting
        light_ambient = (0.0, 0.0, 0.0, 1.0)
        light_diffuse = (1.0, 1.0, 1.0, 1.0)
        light_specular = (1.0, 1.0, 1.0, 1.0)
        light_position = (-100.0, 100.0, 100.0, 0.0)

        mat_ambient = (0.7, 0.7, 0.7, 1.0)
        mat_diffuse = (0.8, 0.8, 0.8, 1.0)
        mat_specular = (1.0, 1.0, 1.0, 1.0)
        high_shininess = (100)

        glEnable(GL_LIGHT0)
        glEnable(GL_NORMALIZE)
        glEnable(GL_COLOR_MATERIAL)
        glEnable(GL_LIGHTING)

        glLightfv(GL_LIGHT0, GL_AMBIENT, light_ambient)
        glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse)
        glLightfv(GL_LIGHT0, GL_SPECULAR,  light_specular)
        glLightfv(GL_LIGHT0, GL_POSITION, light_position)

        glMaterialfv(GL_FRONT, GL_AMBIENT,   mat_ambient)
        glMaterialfv(GL_FRONT, GL_DIFFUSE,   mat_diffuse)
        glMaterialfv(GL_FRONT, GL_SPECULAR,  mat_specular)
        glMaterialfv(GL_FRONT, GL_SHININESS, high_shininess)

        # Transparency
        glEnable(GL_BLEND);
        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);


    def render(self):
        self.clock.record_frame_time()

        if self.is_recording and not self.timer.is_snoozed:
            self.frame_index += 1
            frame_name = "Frame_{0:05d}.jpg".format(self.frame_index)
            self.save_screenshot(frame_name)
            self.timer.snooze()


        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)

        self.colourist.now_background()

        if self.camera.is_rotating:
            self.camera.rotate_z(0.2)
        self.camera.look()

        self.draw_detector()

        glEnable(GL_DEPTH_TEST)
        glEnable(GL_LINE_SMOOTH)
        glShadeModel(GL_FLAT)
        glEnable(GL_LIGHTING)

        for obj in self.shaded_objects:
            obj.draw(self.clock.time, self.spectrum)

        glDisable(GL_LIGHTING)

        for obj in itertools.chain.from_iterable(self.objects.values()):
            obj.draw(self.clock.time)

        self.draw_gui()

        glutSwapBuffers()


    def draw_detector(self):
        glUseProgram(self.shader)
        try:
            self.dom_positions_vbo.bind()
            try:
                glEnableClientState(GL_VERTEX_ARRAY)
                glVertexPointerf(self.dom_positions_vbo)
                glPointSize(2)
                glDrawArrays(GL_POINTS, 0, len(self.dom_positions)*3)
            finally:
                self.dom_positions_vbo.unbind()
                glDisableClientState(GL_VERTEX_ARRAY)
        finally:
            glUseProgram(0)


    def draw_gui(self):
        logo = self.logo
        logo_bytes = self.logo_bytes

        menubar_height = logo.size[1] + 4
        width = glutGet(GLUT_WINDOW_WIDTH)
        height = glutGet(GLUT_WINDOW_HEIGHT)
        glMatrixMode(GL_PROJECTION)
        glPushMatrix()
        glLoadIdentity()
        glOrtho(0.0, width, height, 0.0, -1.0, 10.0)
        glMatrixMode(GL_MODELVIEW)
        glLoadIdentity()
        #glDisable(GL_CULL_FACE)
        glShadeModel(GL_SMOOTH)

        glClear(GL_DEPTH_BUFFER_BIT)

        # Top bar
        #glBegin(GL_QUADS)
        #glColor3f(0.14, 0.49, 0.87)
        #glVertex2f(0, 0)
        #glVertex2f(width - logo.size[0] - 10, 0)
        #glVertex2f(width - logo.size[0] - 10, menubar_height)
        #glVertex2f(0, menubar_height)
        #glEnd()

        try:
            self.draw_colour_legend()
        except TypeError:
            pass

        glPushMatrix()
        glLoadIdentity()
        glRasterPos(4, logo.size[1] + 4)
        glDrawPixels(logo.size[0], logo.size[1], GL_RGB, GL_UNSIGNED_BYTE, logo_bytes)
        glPopMatrix()

        glMatrixMode(GL_PROJECTION)
        glPopMatrix()
        glMatrixMode(GL_MODELVIEW)

        self.colourist.now_text()


        #draw_text_2d("{0}ns".format(int(self.min_hit_time)), width - 80, 20)
        #draw_text_2d("{0}ns".format(int(self.max_hit_time)), width - 80, height - menubar_height - 10)
        #draw_text_2d("{0}ns".format(int((self.min_hit_time + self.max_hit_time) / 2)), width - 80, int(height/2))


        if self.show_help:
            self.display_help()

        if self.show_info:
            self.display_info()

    def draw_colour_legend(self):
        menubar_height = self.logo.size[1] + 4
        width = glutGet(GLUT_WINDOW_WIDTH)
        height = glutGet(GLUT_WINDOW_HEIGHT)
        # Colour legend
        left_x = width - 20
        right_x = width - 10
        min_y = menubar_height + 5
        max_y = height - 20
        time_step_size = math.ceil(self.max_hit_time / 20 / 50) * 50
        hit_times = list(range(int(self.min_hit_time), int(self.max_hit_time), int(time_step_size)))
        if len(hit_times) > 1:
            segment_height = int((max_y - min_y) / len(hit_times))
            glMatrixMode(GL_MODELVIEW)
            glLoadIdentity()
            glDisable(GL_LIGHTING)
            glBegin(GL_QUADS)
            for hit_time in hit_times:
                segment_nr = hit_times.index(hit_time)
                glColor3f(*self.spectrum(hit_time))
                glVertex2f(left_x, max_y - segment_height * segment_nr)
                glVertex2f(right_x, max_y - segment_height * segment_nr)
                glColor3f(*self.spectrum(hit_time + time_step_size))
                glVertex2f(left_x, max_y - segment_height * (segment_nr + 1))
                glVertex2f(right_x, max_y - segment_height * (segment_nr + 1))
            glEnd()

            # Colour legend labels
            self.colourist.now_text()
            for hit_time in hit_times:
                segment_nr = hit_times.index(hit_time)
                draw_text_2d("{0:>5}ns".format(hit_time), width - 80, (height - max_y) + segment_height * segment_nr)

    def resize(self, width, height):
        if width < 400:
            glutReshapeWindow(400, height)
        if height < 300:
            glutReshapeWindow(width, 300)
        if height == 0:
            height = 1

        glViewport(0, 0, width, height)
        glMatrixMode(GL_PROJECTION)
        glLoadIdentity()
        gluPerspective(45.0, float(width)/float(height), 0.1, 10000.0)
        glMatrixMode(GL_MODELVIEW)


    def mouse(self, button, state, x, y):
        if button == GLUT_LEFT_BUTTON:
            if state == GLUT_DOWN:
                self.mouse_x = x
                self.mouse_y = y
                self.camera.is_rotating = False
        if button == 3:
            self.camera.distance = self.camera.distance + 2
        if button == 4:
            self.camera.distance = self.camera.distance - 2

    def keyboard(self, key,  x,  y):
        if(key == "r"):
            self.clock.reset()
        if(key == "h"):
            self.show_help = not self.show_help
        if(key == 'i'):
            self.show_info = not self.show_info
        if(key == "+"):
            self.camera.distance = self.camera.distance - 50
        if(key == "-"):
            self.camera.distance = self.camera.distance + 50
        if(key == "."):
            self.min_tot += 0.5
            self.reload_blob()
        if(key == ","):
            self.min_tot -= 0.5
            self.reload_blob()
        if(key == 'n'):
            self.load_next_blob()
        if(key == 'p'):
            self.load_previous_blob()
        if(key == 'u'):
            self.toggle_secondaries()
        if(key == 't'):
            self.toggle_spectrum()
        if(key == 'x'):
            self.cmap = self.colourist.next_cmap
        if(key == 'm'):
            self.colourist.print_mode = not self.colourist.print_mode
            self.load_logo()
        if(key == 'a'):
            self.camera.is_rotating = not self.camera.is_rotating
        if(key == 'c'):
            self.colourist.cherenkov_cone_enabled = \
                not self.colourist.cherenkov_cone_enabled
        if(key == "s"):
            event_number = self.blob['start_event'][0]
            try:
                neutrino = self.blob['Neutrino']
            except KeyError:
                neutrino_str = ''
            else:
                neutrino_str = str(neutrino).replace(' ', '_').replace(',', '')
                neutrino_str = neutrino_str.replace('Neutrino:', '')
            screenshot_name = "RA_Event{0}_ToTCut{1}{2}_t{3}ns.png".format(
                        event_number,
                        self.min_tot,
                        neutrino_str,
                        int(self.clock.time)
                    )

            self.save_screenshot(screenshot_name)
        if(key == 'v'):
            self.frame_index = 0
            self.is_recording = not self.is_recording
        if(key == " "):
            if self.clock.is_paused:
                self.clock.resume()
            else:
                self.clock.pause()
        if(key in ('q', chr(27))):
            raise SystemExit

    def special_keyboard(self, key, x, z):
        if key == GLUT_KEY_LEFT:
            self.clock.rewind(100)
        if key == GLUT_KEY_RIGHT:
            self.clock.fast_forward(100)

    def drag(self, x, y):
        self.camera.rotate_z(self.mouse_x - x)
        self.camera.move_z(-(self.mouse_y - y)*8)
        self.mouse_x = x
        self.mouse_y = y

    def save_screenshot(self, name='screenshot.png'):
        width = glutGet(GLUT_WINDOW_WIDTH)
        height = glutGet(GLUT_WINDOW_HEIGHT)
        pixelset = (GLubyte * (3*width*height))(0)
        glReadPixels(0, 0, width, height, GL_RGB, GL_UNSIGNED_BYTE, pixelset)
        image = Image.fromstring(mode="RGB", size=(width, height), data=pixelset)
        image = image.transpose(Image.FLIP_TOP_BOTTOM)
        image.save(name)
        print("Screenshot saved as '{0}'.".format(name))


    @property
    def help_string(self):
        if not self._help_string:
            options = {
                'h': 'help',
                'i': 'show event info',
                'n': 'next event',
                'p': 'previous event',
                'LEFT': '+100ns',
                'RIGHT': '-100ns',
                'a': 'enable/disable rotation animation',
                'c': 'enable/disable Cherenkov cone',
                't': 'toggle between spectra',
                'u': 'toggle secondaries',
                'x': 'cycle through colour schemes',
                'm': 'toggle screen/print mode',
                's': 'save screenshot (screenshot.png)',
                'v': 'start/stop recording (Frame_XXXXX.jpg)',
                'r': 'reset time',
                '<space>': 'pause time',
                '+ or -': 'zoom in/out',
                ', or .': 'decrease/increase min_tot by 0.5ns',
                '<esc> or q': 'quit',
                }
            help_string = "Keyboard commands:\n-------------------\n"
            for key in sorted(options.keys()):
                help_string += "{key:>10} : {description}\n" \
                               .format(key=key, description=options[key])
            self._help_string = help_string
        return self._help_string

    @property
    def blob_info(self):
        if not self.blob:
            return ''
        info_text = ''
        try:
            event_number = self.blob['start_event'][0]
            info_text += "Event #{0}, ToT>{1}ns\n" \
                         .format(event_number, self.min_tot)
        except KeyError:
            pass
        try:
            neutrino = self.blob['Neutrino']
            info_text += str(neutrino)
        except KeyError:
            pass
        return info_text

    def display_help(self):
        pos_y = glutGet(GLUT_WINDOW_HEIGHT) - 80
        draw_text_2d(self.help_string, 10, pos_y)

    def display_info(self):
        draw_text_2d("FPS:  {0:.1f}\nTime: {1:.0f} ns"
                     .format(self.clock.fps, self.clock.time),
                     10, 30)
        draw_text_2d(self.blob_info, 150, 30)
示例#23
0
    def __init__(self, detector_file=None, event_file=None, min_tot=None,
                 skip_to_blob=0,
                 width=1000, height=700, x=50, y=50):
        self.camera = Camera()
        self.camera.is_rotating = True

        self.colourist = Colourist()

        current_path = os.path.dirname(os.path.abspath(__file__))

        if not detector_file:
            detector_file = os.path.join(current_path,
                            'data/km3net_jul13_90m_r1494_corrected.detx')

        self.load_logo()

        self.init_opengl(width=width, height=height, x=x, y=y)

        print("OpenGL Version: {0}".format(glGetString(GL_VERSION)))
        self.clock = Clock(speed=100)
        self.timer = Clock(snooze_interval=1/30)
        self.frame_index = 0
        self.event_index = skip_to_blob
        self.is_recording = False
        self.min_tot = min_tot

        VERTEX_SHADER = compileShader("""
        void main() {
            gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
        }""", GL_VERTEX_SHADER)
        FRAGMENT_SHADER = compileShader("""
        void main() {
            gl_FragColor = vec4(0.5, 0.5, 0.5, 1);
        }""", GL_FRAGMENT_SHADER)

        self.shader = compileProgram(VERTEX_SHADER, FRAGMENT_SHADER)


        self.blob = None
        self.objects = {}
        self.shaded_objects = []

        self.mouse_x = None
        self.mouse_y = None

        self.show_secondaries = True
        self.show_help = False
        self._help_string = None
        self.show_info = True

        self.spectrum = None
        self.current_spectrum = 'default'
        self.cmap = self.colourist.default_cmap
        self.min_hit_time = None
        self.max_hit_time = None

        self.detector = Detector(detector_file)
        dom_positions = self.detector.dom_positions
        min_z = min([z for x, y, z in dom_positions])
        max_z = max([z for x, y, z in dom_positions])
        z_shift = (max_z - min_z) / 2
        self.dom_positions = np.array([tuple(pos) for pos in dom_positions], 'f')
        self.camera.target = Position((0, 0, z_shift))
        self.dom_positions_vbo = vbo.VBO(self.dom_positions)

        if event_file:
            self.pump = EvtPump(filename=event_file)
            try:
                self.load_blob(skip_to_blob)
            except IndexError:
                print("Could not load blob at index {0}".format(skip_to_blob))
                print("Starting from the first one...")
                self.load_blob(0)
        else:
            print("No event file specified. Only the detector will be shown.")

        self.clock.reset()
        self.timer.reset()
        glutMainLoop()
示例#24
0
 def test_comments_are_written(self):
     det = Detector(filename=join(TEST_DATA_DIR, 'detx_v3.detx'))
     det.add_comment("foo")
     assert 3 == len(det.comments)
     assert det.comments[2] == "foo"
     assert "# foo" == det.ascii.splitlines()[2]
示例#25
0
class TestDetector(TestCase):
    def setUp(self):
        self.det = Detector()
        self.det._det_file = EXAMPLE_DETX

    def test_parse_header_extracts_correct_det_id(self):
        self.det._parse_header()
        self.assertEqual(1, self.det.det_id)

    def test_parse_header_extracts_correct_n_doms(self):
        self.det._parse_header()
        self.assertEqual(3, self.det.n_doms)

    def test_parse_doms_maps_each_dom_correctly(self):
        self.det._parse()
        expected = {1: (1, 1, 3), 2: (1, 2, 3), 3: (1, 3, 3)}
        self.assertDictEqual(expected, self.det.doms)

    def test_dom_ids(self):
        self.det._parse()
        self.assertEqual((1, 2, 3), tuple(self.det.dom_ids))

    def test_parse_reset_cache(self):
        self.det._parse()
        assert not self.det._dom_positions
        assert not self.det._pmt_angles
        assert not self.det._xy_positions
        self.det.dom_positions
        self.det.pmt_angles
        self.det.xy_positions
        assert self.det._dom_positions
        assert len(self.det._pmt_angles) == 3
        assert len(self.det._xy_positions) == 1
        self.det.reset_caches()
        assert not self.det._dom_positions
        assert not self.det._pmt_angles
        assert not self.det._xy_positions

    def test_parse_doms_maps_each_dom_correctly_for_mixed_pmt_ids(self):
        self.det._det_file = EXAMPLE_DETX_MIXED_IDS
        self.det._parse()
        expected = {8: (1, 1, 3), 7: (1, 2, 3), 6: (1, 3, 3)}
        self.assertDictEqual(expected, self.det.doms)

    def test_dom_positions(self):
        self.det._parse()
        assert np.allclose([1.49992331, 1.51893187, 1.44185513],
                           self.det.dom_positions[1])
        assert np.allclose([2.49992331, 2.51893187, 2.44185513],
                           self.det.dom_positions[2])
        assert np.allclose([3.49992331, 3.51893187, 3.44185513],
                           self.det.dom_positions[3])

    def test_xy_positions(self):
        self.det._parse()
        assert len(self.det.xy_positions) == 1
        assert np.allclose([1.49992331, 1.51893187], self.det.xy_positions[0])

    def test_correct_number_of_pmts(self):
        self.det._parse()
        assert 9 == len(self.det.pmts)

    def test_pmt_attributes(self):
        self.det._parse()
        assert (1, 2, 3, 4, 5, 6, 7, 8, 9) == tuple(self.det.pmts.pmt_id)
        assert np.allclose([1.1, 1.4, 1.7, 2.1, 2.4, 2.7, 3.1, 3.4, 3.7],
                           self.det.pmts.pos_x)
        assert np.allclose((1.7, 1.8, 1.9), self.det.pmts.pos[2])
        assert np.allclose((0.1, 0.2, -1.3), self.det.pmts.dir[8])

    def test_pmt_index_by_omkey(self):
        self.det._parse()
        assert 5 == self.det._pmt_index_by_omkey[(1, 2, 2)]
        assert 0 == self.det._pmt_index_by_omkey[(1, 1, 0)]
        assert 4 == self.det._pmt_index_by_omkey[(1, 2, 1)]
        assert 1 == self.det._pmt_index_by_omkey[(1, 1, 1)]

    def test_pmt_index_by_pmt_id(self):
        self.det._parse()
        assert 0 == self.det._pmt_index_by_pmt_id[1]

    def test_pmt_with_id_returns_correct_omkeys(self):
        self.det._parse()
        pmt = self.det.pmt_with_id(1)
        assert (1, 1, 0) == (pmt.du, pmt.floor, pmt.channel_id)
        pmt = self.det.pmt_with_id(5)
        assert (1, 2, 1) == (pmt.du, pmt.floor, pmt.channel_id)

    def test_pmt_with_id_returns_correct_omkeys_with_mixed_pmt_ids(self):
        self.det._det_file = EXAMPLE_DETX_MIXED_IDS
        self.det._parse()
        pmt = self.det.pmt_with_id(73)
        assert (1, 2, 1) == (pmt.du, pmt.floor, pmt.channel_id)
        pmt = self.det.pmt_with_id(81)
        assert (1, 1, 1) == (pmt.du, pmt.floor, pmt.channel_id)

    def test_pmt_with_id_raises_exception_for_invalid_id(self):
        self.det._parse()
        with self.assertRaises(KeyError):
            self.det.pmt_with_id(100)

    def test_get_pmt(self):
        self.det._det_file = EXAMPLE_DETX_MIXED_IDS
        self.det._parse()
        pmt = self.det.get_pmt(7, 2)
        assert (1, 2, 2) == (pmt.du, pmt.floor, pmt.channel_id)

    def test_xy_pos(self):
        self.det._parse()
        xy = self.det.xy_positions
        assert xy is not None

    def test_ascii(self):
        detx_string = "\n".join((
            "1 3",
            "1 1 1 3",
            " 1 1.1 1.2 1.3 1.1 2.1 3.1 10.0",
            " 2 1.4 1.5 1.6 4.1 5.1 6.1 20.0",
            " 3 1.7 1.8 1.9 7.1 8.1 9.1 30.0",
            "2 1 2 3",
            " 4 2.1 2.2 2.3 1.2 2.2 3.2 40.0",
            " 5 2.4 2.5 2.6 4.2 5.2 6.2 50.0",
            " 6 2.7 2.8 2.9 7.2 8.2 9.2 60.0",
            "3 1 3 3",
            " 7 3.1 3.2 3.3 1.3 2.3 3.3 70.0",
            " 8 3.4 3.5 3.6 4.3 5.3 6.3 80.0",
            " 9 3.7 3.8 3.9 7.3 8.3 9.3 90.0\n",
        ))
        detx_fob = StringIO(detx_string)

        self.det = Detector()
        self.det._det_file = detx_fob
        self.det._parse()
        assert detx_string == self.det.ascii

    def test_ascii_with_mixed_dom_ids(self):
        detx_string = "\n".join((
            "1 3",
            "8 1 1 3",
            " 1 1.1 1.2 1.3 1.1 2.1 3.1 10.0",
            " 2 1.4 1.5 1.6 4.1 5.1 6.1 20.0",
            " 3 1.7 1.8 1.9 7.1 8.1 9.1 30.0",
            "4 1 2 3",
            " 4 2.1 2.2 2.3 1.2 2.2 3.2 40.0",
            " 5 2.4 2.5 2.6 4.2 5.2 6.2 50.0",
            " 6 2.7 2.8 2.9 7.2 8.2 9.2 60.0",
            "9 1 3 3",
            " 7 3.1 3.2 3.3 1.3 2.3 3.3 70.0",
            " 8 3.4 3.5 3.6 4.3 5.3 6.3 80.0",
            " 9 3.7 3.8 3.9 7.3 8.3 9.3 90.0\n",
        ))
        detx_fobj = StringIO(detx_string)

        self.det = Detector()
        self.det._det_file = detx_fobj
        self.det._parse()
        assert detx_string == self.det.ascii

    def test_init_from_string(self):
        detx_string = "\n".join((
            "1 3",
            "8 1 1 3",
            " 1 1.1 1.2 1.3 1.1 2.1 3.1 10.0",
            " 2 1.4 1.5 1.6 4.1 5.1 6.1 20.0",
            " 3 1.7 1.8 1.9 7.1 8.1 9.1 30.0",
            "4 1 2 3",
            " 4 2.1 2.2 2.3 1.2 2.2 3.2 40.0",
            " 5 2.4 2.5 2.6 4.2 5.2 6.2 50.0",
            " 6 2.7 2.8 2.9 7.2 8.2 9.2 60.0",
            "9 1 3 3",
            " 7 3.1 3.2 3.3 1.3 2.3 3.3 70.0",
            " 8 3.4 3.5 3.6 4.3 5.3 6.3 80.0",
            " 9 3.7 3.8 3.9 7.3 8.3 9.3 90.0\n",
        ))
        det = Detector(string=detx_string)
        assert 1 == det.n_dus
        assert 3 == det.n_doms

    def test_detx_format_version_1(self):
        det = Detector(filename=data_path("detx/detx_v1.detx"))
        assert 2 == det.n_dus
        assert 6 == det.n_doms
        assert 3 == det.n_pmts_per_dom
        assert 1 == det.version
        self.assertListEqual([1.1, 1.2, 1.3], list(det.pmts.pos[0]))
        self.assertListEqual([3.4, 3.5, 3.6], list(det.pmts.pos[7]))
        self.assertListEqual([23.4, 23.5, 23.6], list(det.pmts.pos[16]))

    def test_detx_v1_is_the_same_ascii(self):
        det = Detector(filename=data_path("detx/detx_v1.detx"))
        with open(data_path("detx/detx_v1.detx"), "r") as fobj:
            assert fobj.read() == det.ascii

    def test_detx_format_version_2(self):
        det = Detector(filename=data_path("detx/detx_v2.detx"))
        assert 2 == det.n_dus
        assert 6 == det.n_doms
        assert 3 == det.n_pmts_per_dom
        assert 256500.0 == det.utm_info.easting
        assert 4743000.0 == det.utm_info.northing
        assert "WGS84" == det.utm_info.ellipsoid
        assert "32N" == det.utm_info.grid
        assert -2425.0 == det.utm_info.z
        assert 1500000000.1 == det.valid_from
        assert 9999999999.0 == det.valid_until
        assert 2 == det.version
        self.assertListEqual([1.1, 1.2, 1.3], list(det.pmts.pos[0]))
        self.assertListEqual([3.4, 3.5, 3.6], list(det.pmts.pos[7]))
        self.assertListEqual([23.4, 23.5, 23.6], list(det.pmts.pos[16]))

    def test_detx_v2_is_the_same_ascii(self):
        det = Detector(filename=data_path("detx/detx_v2.detx"))
        with open(data_path("detx/detx_v2.detx"), "r") as fobj:
            assert fobj.read() == det.ascii

    def test_detx_format_version_3(self):
        det = Detector(filename=data_path("detx/detx_v3.detx"))
        assert 2 == det.n_dus
        assert 6 == det.n_doms
        assert 3 == det.n_pmts_per_dom
        assert 256500.0 == det.utm_info.easting
        assert 4743000.0 == det.utm_info.northing
        assert "WGS84" == det.utm_info.ellipsoid
        assert "32N" == det.utm_info.grid
        assert -2425.0 == det.utm_info.z
        assert 1500000000.1 == det.valid_from
        assert 9999999999.0 == det.valid_until
        assert 3 == det.version
        self.assertListEqual([1.1, 1.2, 1.3], list(det.pmts.pos[0]))
        self.assertListEqual([3.4, 3.5, 3.6], list(det.pmts.pos[7]))
        self.assertListEqual([23.4, 23.5, 23.6], list(det.pmts.pos[16]))

    def test_detector_repr(self):
        det = Detector(filename=data_path("detx/detx_v3.detx"))
        assert "Detector id: '23', n_doms: 6, dus: [1, 2]" == repr(det)

    def test_detx_format_version_3_with_whitespace(self):
        det = Detector(filename=data_path("detx/detx_v3_whitespace.detx"))
        assert 2 == det.n_dus
        assert 6 == det.n_doms
        assert 3 == det.n_pmts_per_dom
        assert 256500.0 == det.utm_info.easting
        assert 4743000.0 == det.utm_info.northing
        assert "WGS84" == det.utm_info.ellipsoid
        assert "32N" == det.utm_info.grid
        assert -2425.0 == det.utm_info.z
        assert 1500000000.1 == det.valid_from
        assert 9999999999.0 == det.valid_until
        assert 3 == det.version
        self.assertListEqual([1.1, 1.2, 1.3], list(det.pmts.pos[0]))
        self.assertListEqual([3.4, 3.5, 3.6], list(det.pmts.pos[7]))
        self.assertListEqual([23.4, 23.5, 23.6], list(det.pmts.pos[16]))

    def test_detx_format_comments(self):
        det = Detector(filename=data_path("detx/detx_v1.detx"))
        assert len(det.comments) == 0

        det = Detector(filename=data_path("detx/detx_v2.detx"))
        assert len(det.comments) == 0

        det = Detector(filename=data_path("detx/detx_v3.detx"))
        assert len(det.comments) == 2
        assert " a comment line" == det.comments[0]
        assert " another comment line starting with '#'" == det.comments[1]

    def test_comments_are_written(self):
        det = Detector(filename=data_path("detx/detx_v3.detx"))
        det.add_comment("foo")
        assert 3 == len(det.comments)
        assert det.comments[2] == "foo"
        assert "# foo" == det.ascii.splitlines()[2]

    def test_detx_v3_is_the_same_ascii(self):
        det = Detector(filename=data_path("detx/detx_v3.detx"))
        with open(data_path("detx/detx_v3.detx"), "r") as fobj:
            assert fobj.read() == det.ascii

    def test_detx_v4(self):
        det = Detector(filename=data_path("detx/detx_v4.detx"))
        assert np.allclose([119.6, -12.2, 192.77],
                           det.dom_positions[808956908],
                           atol=1e-2)
        assert np.allclose([119.6, -12.2, 97.44],
                           det.dom_positions[808981864],
                           atol=1e-2)
        assert det.n_doms == 90
        assert det.det_id == 44
        assert det.n_pmts_per_dom == 31
        assert det.n_dus == 5
        assert np.allclose(
            det.doms[808945480],
            [
                1,
                5,
                31,
                86.500,
                9.100,
                66.821,
                1.000000,
                0.000000,
                0.000000,
                0.000000,
                0.000,
            ],
            atol=1e-2,
        )
        assert np.allclose(
            np.array([[86.5, 9.1], [86.6, 6.6], [109.6, 5.9], [97.8, -9.6],
                      [119.6, -12.2]]),
            det.xy_positions,
        )
        assert np.allclose(
            [
                3,
                0.844,
                0.449,
                0.295,
                808981864,
                5,
                8,
                13367,
                119.768,
                -12.11,
                97.5,
                0,
                207863.242,
            ],
            list(det.get_pmt(808981864, 3)),
        )

    def test_detx_v5(self):
        det = Detector(filename=data_path("detx/detx_v5.detx"))
        assert np.allclose([464.4, 564.7, 190.583],
                           det.dom_positions[808956908],
                           atol=1e-2)
        assert np.allclose([464.4, 564.7, 95.389],
                           det.dom_positions[808981864],
                           atol=1e-2)
        assert det.n_doms == 114
        assert det.det_id == 49
        assert det.n_pmts_per_dom == 31
        assert det.n_dus == 6
        assert np.allclose(
            det.doms[808981864],
            [
                1.0000000e01,
                8.0000000e00,
                3.1000000e01,
                4.6440000e02,
                5.6470000e02,
                9.5389000e01,
                9.9995400e-01,
                -7.8470000e-03,
                3.9110000e-03,
                4.0080000e-03,
                0.0000000e00,
                3.7861343e04,
            ],
            atol=1e-2,
        )
        assert np.allclose(
            np.array([
                [484.6, 564.65],
                [464.4, 564.7],
                [442.5, 567.45],
                [474.15, 583.45],
                [454.2, 583.0],
                [431.1, 583.5],
            ]),
            det.xy_positions,
        )
        assert np.allclose(
            [
                3,
                0.73205,
                0.614161,
                0.29479,
                808981864,
                10,
                8,
                13367,
                464.546,
                564.823,
                95.448,
                0,
                207862.961,
            ],
            list(det.get_pmt(808981864, 3)),
        )
示例#26
0
 def setUp(self):
     self.det = Detector()
     self.det._det_file = EXAMPLE_DETX
示例#27
0
    def test_center_of_mass_with_another_detx(self):
        det = Detector()
        det._det_file = EXAMPLE_DETX_RADIAL
        det._parse()

        assert np.allclose([-0.2, 0.0, 0.2], det.com)
示例#28
0
class RainbowAlga(object):
    def __init__(self, width=800, height=600, x=112, y=84):

        self.init_opengl(width=width, height=height, x=x, y=y)

        print("OpenGL Version: {0}".format(glGetString(GL_VERSION)))
        self.clock = Clock(speed=100)
        self.timer = Clock(snooze_interval=1/30)
        self.frame_index = 0
        self.event_index = 0
        self.is_recording = False

        VERTEX_SHADER = compileShader("""
        void main() {
            gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
        }""", GL_VERTEX_SHADER)
        FRAGMENT_SHADER = compileShader("""
        void main() {
            gl_FragColor = vec4(0.8, 0.8, 0.8, 1);
        }""", GL_FRAGMENT_SHADER)

        self.shader = compileProgram(VERTEX_SHADER, FRAGMENT_SHADER)

        self.coordsys = vbo.VBO(
            np.array([
                [-1, 0, 0],
                [1, 0, 0],
                [0, -1, 0],
                [0, 1, 0],
                [0, 0, -1],
                [0, 0, 1]
                ], 'f')
            )

        self.blob = None
        self.objects = []
        self.shaded_objects = []

        self.mouse_x = None
        self.mouse_y = None

        self.show_help = False
        self._help_string = None
        self.show_info = False

        self.spectrum = None

        self.detector = Detector('/Users/tamasgal/Data/KM3NeT/Detector/km3net_jul13_90m.detx')
        self.dom_positions = np.array([tuple(pos) for pos in self.detector.dom_positions], 'f')
        self.min_z = min([z for x, y, z in self.dom_positions])
        self.max_z = max([z for x, y, z in self.dom_positions])
        camera.target = Position((0, 0, (self.max_z - self.min_z) / 2))
        self.dom_positions_vbo = vbo.VBO(self.dom_positions)

        self.pump = EvtPump(filename='/Users/tamasgal/Data/KM3NeT/Luigi/nueCC.evt')
        self.load_blob(0)

        self.clock.reset()
        self.timer.reset()
        glutMainLoop()

    def load_blob(self, index=0):
        blob = self.blob = self.pump.get_blob(index)

        self.objects = []
        self.shaded_objects = []

        tracks = blob['TrackIns']
        for track in tracks:
            particle = Particle(track.pos.x, track.pos.y, track.pos.z,
                                track.dir.x, track.dir.y, track.dir.z,
                                track.time, constants.c, track.length)
            self.objects.append(particle)
        hits = blob['EvtRawHits']
        hit_times = []
        step_size = int(len(hits) / 100) + 1
        for hit in hits[::step_size]:
            hit_times.append(hit.time)
            x, y, z = self.detector.pmt_with_id(hit.pmt_id).pos
            self.shaded_objects.append(Hit(x, y, z, hit.time, 5))

        def spectrum(time):
            min_time = min(hit_times)
            max_time = max(hit_times)
            diff = max_time - min_time
            one_percent = diff/100
            progress = (time - min_time) / one_percent / 100
            return (1-progress, 0, progress)
        self.spectrum = spectrum

    def load_next_blob(self):
        try:
            self.load_blob(self.event_index + 1)
        except IndexError:
            return
        else:
            self.clock.reset()
            self.event_index += 1

    def load_previous_blob(self):
        try:
            self.load_blob(self.event_index - 1)
        except IndexError:
            return
        else:
            self.clock.reset()
            self.event_index -= 1


    def init_opengl(self, width, height, x, y):
        glutInit()
        glutInitWindowPosition(x, y)
        glutInitWindowSize(width, height)
        glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH | GLUT_MULTISAMPLE)
        glutCreateWindow("Rainbow Alga")
        glutDisplayFunc(self.render)
        glutIdleFunc(self.render)
        glutReshapeFunc(self.resize)

        glutMouseFunc(self.mouse)
        glutMotionFunc(self.drag)
        glutKeyboardFunc(self.keyboard)
        glutSpecialFunc(self.special_keyboard)

        glClearDepth(1.0)
        glClearColor(0.0, 0.0, 0.0, 0.0)
        glMatrixMode(GL_PROJECTION)
        glLoadIdentity()
        glFrustum(-1.0, 1.0, -1.0, 1.0, 1.0, 3000)
        glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT)


        # Lighting
        light_ambient = (0.0, 0.0, 0.0, 1.0)
        light_diffuse = (1.0, 1.0, 1.0, 1.0)
        light_specular = (1.0, 1.0, 1.0, 1.0)
        light_position = (-100.0, 100.0, 100.0, 0.0)

        mat_ambient = (0.7, 0.7, 0.7, 1.0)
        mat_diffuse = (0.8, 0.8, 0.8, 1.0)
        mat_specular = (1.0, 1.0, 1.0, 1.0)
        high_shininess = (100)

        glEnable(GL_LIGHT0)
        glEnable(GL_NORMALIZE)
        glEnable(GL_COLOR_MATERIAL)
        glEnable(GL_LIGHTING)

        glLightfv(GL_LIGHT0, GL_AMBIENT, light_ambient)
        glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse)
        glLightfv(GL_LIGHT0, GL_SPECULAR,  light_specular)
        glLightfv(GL_LIGHT0, GL_POSITION, light_position)

        glMaterialfv(GL_FRONT, GL_AMBIENT,   mat_ambient)
        glMaterialfv(GL_FRONT, GL_DIFFUSE,   mat_diffuse)
        glMaterialfv(GL_FRONT, GL_SPECULAR,  mat_specular)
        glMaterialfv(GL_FRONT, GL_SHININESS, high_shininess)


    def render(self):
        self.clock.record_frame_time()

        if self.is_recording and not self.timer.is_snoozed:
            self.frame_index += 1
            frame_name = "Frame_{0:05d}.jpg".format(self.frame_index)
            self.save_screenshot(frame_name)
            self.timer.snooze()


        glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)

        if camera.is_rotating:
            camera.rotate_z(0.2)
        camera.look()

        self.draw_detector()

        glEnable(GL_DEPTH_TEST)
        glEnable(GL_LINE_SMOOTH)
        glShadeModel(GL_FLAT)
        glEnable(GL_LIGHTING)

        for obj in self.shaded_objects:
            obj.draw(self.clock.time, self.spectrum)

        glDisable(GL_LIGHTING)

        for obj in self.objects:
            obj.draw(self.clock.time)

        self.draw_gui()


        glutSwapBuffers()

    def draw_detector(self):
        glUseProgram(self.shader)
        try:
            self.dom_positions_vbo.bind()
            try:
                glEnableClientState(GL_VERTEX_ARRAY)
                glVertexPointerf(self.dom_positions_vbo)
                glPointSize(2)
                glDrawArrays(GL_POINTS, 0, len(self.dom_positions)*3)
            finally:
                self.dom_positions_vbo.unbind()
                glDisableClientState(GL_VERTEX_ARRAY)
        finally:
            glUseProgram(0)


    def draw_gui(self):
        menubar_height = logo.size[1] + 4
        width = glutGet(GLUT_WINDOW_WIDTH)
        height = glutGet(GLUT_WINDOW_HEIGHT)
        glMatrixMode(GL_PROJECTION)
        glPushMatrix()
        glLoadIdentity()
        glOrtho(0.0, width, height, 0.0, -1.0, 10.0)
        glMatrixMode(GL_MODELVIEW)
        glLoadIdentity()
        glDisable(GL_CULL_FACE)

        glClear(GL_DEPTH_BUFFER_BIT)

        glBegin(GL_QUADS)
        glColor3f(0.14, 0.49, 0.87)
        glVertex2f(0, 0)
        glVertex2f(width - logo.size[0] - 10, 0)
        glVertex2f(width - logo.size[0] - 10, menubar_height)
        glVertex2f(0, menubar_height)
        glEnd()

        glPushMatrix()
        glLoadIdentity()
        glRasterPos(width - logo.size[0] - 4, logo.size[1] + 2)
        glDrawPixels(logo.size[0], logo.size[1], GL_RGB, GL_UNSIGNED_BYTE, logo_bytes)
        glPopMatrix()

        glMatrixMode(GL_PROJECTION)
        glPopMatrix()
        glMatrixMode(GL_MODELVIEW)

        glColor3f(1.0, 1.0, 1.0)

        draw_text_2d("FPS:  {0:.1f}\nTime: {1:.0f} ns"
                     .format(self.clock.fps, self.clock.time),
                     10, 30)
        if self.show_help:
            self.display_help()

        if self.show_info:
            self.display_info()


    def resize(self, width, height):
        if width < 400:
            glutReshapeWindow(400, height)
        if height < 300:
            glutReshapeWindow(width, 300)
        if height == 0:
            height = 1

        glViewport(0, 0, width, height)
        glMatrixMode(GL_PROJECTION)
        glLoadIdentity()
        gluPerspective(45.0, float(width)/float(height), 0.1, 10000.0)
        glMatrixMode(GL_MODELVIEW)


    def mouse(self, button, state, x, y):
        if button == GLUT_LEFT_BUTTON:
            if state == GLUT_DOWN:
                self.mouse_x = x
                self.mouse_y = y
                camera.is_rotating = False
            else:
                camera.is_rotating = True

        if button == 3:
            camera.distance = camera.distance + 2
        if button == 4:
            camera.distance = camera.distance - 2

    def keyboard(self, key,  x,  y):
        if(key == "r"):
            self.clock.reset()
        if(key == "h"):
            self.show_help = not self.show_help
        if(key == 'i'):
            self.show_info = not self.show_info
        if(key == "+"):
            camera.distance = camera.distance - 50
        if(key == "-"):
            camera.distance = camera.distance + 50

        if(key == 'n'):
            self.load_next_blob()

        if(key == 'p'):
            self.load_previous_blob()

        if(key == "s"):
            self.save_screenshot()

        if(key == 'v'):
            self.frame_index = 0
            self.is_recording = not self.is_recording
        if(key == " "):
            if self.clock.is_paused:
                self.clock.resume()
            else:
                self.clock.pause()
        if(key in ('q', chr(27))):
            raise SystemExit

    def special_keyboard(self, key, x, z):
        if key == GLUT_KEY_LEFT:
            self.clock.rewind(100)
        if key == GLUT_KEY_RIGHT:
            self.clock.fast_forward(100)

    def drag(self, x, y):
        camera.rotate_z(self.mouse_x - x)
        camera.move_z(-(self.mouse_y - y)*8)
        self.mouse_x = x
        self.mouse_y = y

    def save_screenshot(self, name='screenshot.png'):
        width = glutGet(GLUT_WINDOW_WIDTH)
        height = glutGet(GLUT_WINDOW_HEIGHT)
        pixelset = (GLubyte * (3*width*height))(0)
        glReadPixels(0, 0, width, height, GL_RGB, GL_UNSIGNED_BYTE, pixelset)
        image = Image.fromstring(mode="RGB", size=(width, height), data=pixelset)
        image = image.transpose(Image.FLIP_TOP_BOTTOM)
        image.save(name)
        print("Screenshot saved as '{0}'.".format(name))


    @property
    def help_string(self):
        if not self._help_string:
            options = {
                'h': 'help',
                'i': 'show event info',
                'n': 'next event',
                'p': 'previous event',
                'LEFT': '+100ns',
                'RIGHT': '-100ns',
                's': 'save screenshot (screenshot.png)',
                'v': 'start/stop recording (Frame_XXXXX.jpg)',
                'r': 'reset time',
                '<space>': 'pause time',
                '+': 'zoom in',
                '-': 'zoom out',
                '<esc> or q': 'quit',
                }
            help_string = "Keyboard commands:\n-------------------\n"
            for key in sorted(options.keys()):
                help_string += "{key:>10} : {description}\n" \
                               .format(key=key, description=options[key])
            self._help_string = help_string
        return self._help_string

    @property
    def blob_info(self):
        if not self.blob:
            return ''
        info_text = ''
        try:
            event_number = self.blob['start_event'][0]
            info_text += "Event #{0}\n".format(event_number)
        except KeyError:
            pass
        return info_text

    def display_help(self):
        pos_y = glutGet(GLUT_WINDOW_HEIGHT) - 80
        draw_text_2d(self.help_string, 10, pos_y)

    def display_info(self):
        pos_y = glutGet(GLUT_WINDOW_HEIGHT) - 100
        draw_text_2d(self.blob_info, 10, pos_y)
示例#29
0
 def test_detector_repr(self):
     det = Detector(filename=data_path("detx/detx_v3.detx"))
     assert "Detector id: '23', n_doms: 6, dus: [1, 2]" == repr(det)
示例#30
0
    def test_center_of_mass(self):
        det = Detector()
        det._det_file = EXAMPLE_DETX
        det._parse()

        assert np.allclose([2.4, 2.5, 2.6], det.com)
示例#31
0
class RainbowAlga(object):
    def __init__(self,
                 detector_file=None,
                 event_file=None,
                 min_tot=None,
                 skip_to_blob=0,
                 width=1000,
                 height=700,
                 x=50,
                 y=50):
        self.camera = Camera()
        self.camera.is_rotating = True

        self.colourist = Colourist()

        current_path = os.path.dirname(os.path.abspath(__file__))

        if not detector_file:
            filepath = 'data/km3net_jul13_90m_r1494_corrected.detx'
            detector_file = os.path.join(current_path, filepath)

        self.load_logo()

        self.init_opengl(width=width, height=height, x=x, y=y)

        print("OpenGL Version: {0}".format(glGetString(GL_VERSION)))
        self.clock = Clock(speed=100)
        self.timer = Clock(snooze_interval=1 / 30)
        self.frame_index = 0
        self.event_index = skip_to_blob
        self.is_recording = False
        self.min_tot = min_tot
        self.time_offset = 0

        VERTEX_SHADER = compileShader(
            """
        void main() {
            gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
        }""", GL_VERTEX_SHADER)
        FRAGMENT_SHADER = compileShader(
            """
        void main() {
            gl_FragColor = vec4(0.5, 0.5, 0.5, 1);
        }""", GL_FRAGMENT_SHADER)

        self.shader = compileProgram(VERTEX_SHADER, FRAGMENT_SHADER)

        self.blob = None
        self.objects = {}
        self.shaded_objects = []

        self.mouse_x = None
        self.mouse_y = None

        self.show_secondaries = True
        self.show_help = False
        self._help_string = None
        self.show_info = True

        self.spectrum = None
        self.current_spectrum = 'default'
        self.cmap = self.colourist.default_cmap
        self.min_hit_time = None
        self.max_hit_time = None

        if detector_file.endswith('.detx'):
            self.detector = Detector(filename=detector_file)
            self.geometry = Calibration(filename=detector_file)
        else:
            self.detector = Detector(det_id=detector_file)
            self.geometry = Calibration(det_id=detector_file)

        dom_pos = self.detector.dom_positions.values()
        min_z = min([z for x, y, z in dom_pos])
        max_z = max([z for x, y, z in dom_pos])
        z_shift = (max_z - min_z) / 2
        self.dom_positions = np.array([tuple(pos) for pos in dom_pos], 'f')
        self.camera.target = Vec3(0, 0, z_shift)
        self.dom_positions_vbo = vbo.VBO(self.dom_positions)

        if event_file:
            self.pump = GenericPump(event_file)

            try:
                self.load_blob(skip_to_blob)
            except IndexError:
                print("Could not load blob at index {0}".format(skip_to_blob))
                print("Starting from the first one...")
                self.load_blob(0)
        else:
            print("No event file specified. Only the detector will be shown.")

        self.clock.reset()
        self.timer.reset()
        glutMainLoop()

    def load_logo(self):
        if self.colourist.print_mode:
            image = 'images/km3net_logo_print.bmp'
        else:
            image = 'images/km3net_logo.bmp'

        current_path = os.path.dirname(os.path.abspath(__file__))

        image_path = os.path.join(current_path, image)
        self.logo = Image.open(image_path)
        # Create a raw string from the image data - data will be unsigned bytes
        # RGBpad, no stride (0), and first line is top of image (-1)
        self.logo_bytes = self.logo.tobytes("raw", "RGB", 0, -1)

    def load_blob(self, index=0):
        print("Loading blob {0}...".format(index))
        blob = self.blob = self.pump.get_blob(index)

        self.objects = {}
        self.shaded_objects = []
        self.time_offset = 0

        try:
            self.add_neutrino(blob)
        except TypeError:
            pass
        self.add_mc_tracks(blob)
        self.add_reco_tracks(blob)

        self.initialise_spectrum(blob, style=self.current_spectrum)

    def reload_blob(self):
        self.load_blob(self.event_index)

    def initialise_spectrum(self, blob, style="default"):

        if style == 'default':
            hits = self.extract_hits(blob)
            if hits is None:
                return
            hits = self.remove_hidden_hits(hits)

            hit_times = hits.time

            if len(hit_times) == 0:
                log.warn("No hits left after applying cuts.")
                return

            self.min_hit_time = min(hit_times)
            self.max_hit_time = max(hit_times)

            self.time_offset = self.min_hit_time

            self.clock._global_offset = self.min_hit_time / self.clock.speed

            def spectrum(time, hit=None):
                min_time = self.min_hit_time
                max_time = self.max_hit_time
                diff = max_time - min_time
                one_percent = diff / 100
                try:
                    progress = (time - min_time) / one_percent / 100
                except ZeroDivisionError:
                    progress = 0
                return tuple(self.cmap(progress))[:3]

            self.spectrum = spectrum

        if style in [
                'time_residuals_point_source', 'time_residuals_cherenkov_cone'
        ]:
            try:
                track_ins = blob['McTracks']
            except KeyError:
                log.error("No tracks found to determine Cherenkov parameters!")
                self.current_spectrum = "default"
                return
            # most_energetic_muon = max(track_ins, key=lambda t: t.E)
            muon_pos = np.mean(track_ins.pos)
            muon_dir = track_ins.dir[0]
            # if not pdg2name(most_energetic_muon.particle_type)  \
            #         in ['mu-', 'mu+']:
            #     log.error("No muon found to determine Cherenkov parameters!")
            #     self.current_spectrum = "default"
            #     return

            hits = self.extract_hits(blob)
            if hits is None:
                return
            hits = self.first_om_hits(hits)

            def cherenkov_time(pmt_pos):
                """Calculates Cherenkov arrival time in [ns]"""
                v = pmt_pos - muon_pos
                l = v.dot(muon_dir)
                k = np.sqrt(v.dot(v) - l**2)
                v_g = constants.c_water_km3net
                theta = constants.theta_cherenkov_water_km3net
                a_1 = k / np.tan(theta)
                a_2 = k / np.sin(theta)
                t_c = 1 / constants.c * (l - a_1) + 1 / v_g * a_2
                return t_c * 1e9

            def point_source_time(pmt_pos):
                """Calculates cherenkov arrival time with cascade hypothesis"""
                vertex_pos = blob['Neutrino'].pos

                v = pmt_pos - vertex_pos
                v = np.sqrt(v.dot(v))
                v_g = constants.c_water_antares
                t_c = v / v_g
                return t_c * 1e9 + blob['Neutrino'].time

            self.min_hit_time = -100
            self.max_hit_time = 100

            def spectrum(time, hit=None):
                if hit:
                    pmt_pos = self._get_pmt_pos_from_hit(hit)
                    if not hit.t_cherenkov:
                        if style == 'time_residuals_point_source':
                            t_c = point_source_time(pmt_pos)
                        elif style == 'time_residuals_cherenkov_cone':
                            t_c = cherenkov_time(pmt_pos)
                        hit.t_cherenkov = t_c
                        log.debug("Hit time: {0}, Expected: {1}, "
                                  "Time Residual: {2}".format(
                                      time, t_c, time - t_c))
                    time = time - hit.t_cherenkov

                diff = self.max_hit_time - self.min_hit_time
                one_percent = diff / 100
                try:
                    progress = (time - self.min_hit_time) / one_percent / 100
                    if progress > 1:
                        progress = 1
                except ZeroDivisionError:
                    progress = 0
                return tuple(self.cmap(progress))[:3]

            self.spectrum = spectrum

    def toggle_spectrum(self):
        if self.current_spectrum == 'default':
            print('cherenkov')
            self.current_spectrum = 'time_residuals_cherenkov_cone'
        elif self.current_spectrum == 'time_residuals_cherenkov_cone':
            print('cherenkov')
            self.current_spectrum = 'time_residuals_point_source'
        else:
            print('default')
            self.current_spectrum = 'default'
        self.reload_blob()

    def remove_hidden_hits(self, hits):
        log.debug("Skipping removing hidden hits")
        for hit in hits:
            rb_hit = Hit(hit.pos_x, hit.pos_y, hit.pos_z, hit.time, 0, 0,
                         hit.tot)
            self.shaded_objects.append(rb_hit)
        return hits

        log.debug("Removing hidden hits")
        om_hit_map = {}
        om_combs = set(zip(hits.du, hits.floor))
        for om_comb in om_combs:
            du, floor = om_comb
            om_hit_map[om_comb] = hits[(hits.du == du) & (hits.floor == floor)]
        print(om_hit_map)
        for hit in hits:
            x, y, z = hit.pos_x, hit.pos_y, hit.pos_z
            rb_hit = Hit(x, y, z, hit.time, hit.pmt_id, hit.id, hit.tot)
            om_hit_map.setdefault(line_floor, []).append(rb_hit)
        hits = []
        for om, om_hits in om_hit_map.items():
            largest_hit = None
            for hit in om_hits:
                if largest_hit:
                    if hit.tot > largest_hit.tot:
                        hidden_hits = om_hits[:om_hits.index(hit)]
                        hit.replaces_hits = hidden_hits
                        hits.append(hit)
                        self.shaded_objects.append(hit)
                        largest_hit = hit
                else:
                    hits.append(hit)
                    self.shaded_objects.append(hit)
                    largest_hit = hit
        print("Number of hits after removing hidden ones: {0}".format(
            len(hits)))
        return hits

    def first_om_hits(self, hits):
        log.debug("Entering first_om_hits()")
        print(hits.time)
        om_hit_map = {}
        for hit in hits:
            if hit.time < 0:
                continue
            x, y, z = self._get_pmt_pos_from_hit(hit)
            rb_hit = Hit(x, y, z, hit.time, hit.pmt_id, hit.id, hit.tot)
            try:  # EVT file
                line_floor = self.detector.pmtid2omkey(hit.pmt_id)[:2]
            except KeyError:  # Other files
                line, floor, _ = self.detector.doms[hit.dom_id]
                line_floor = line, floor
            om_hit_map.setdefault(line_floor, []).append(rb_hit)
        hits = []
        for om, om_hits in om_hit_map.items():
            first_hit = om_hits[0]
            self.shaded_objects.append(first_hit)
            hits.append(first_hit)
        print("Number of first OM hits: {0}".format(len(hits)))
        return hits

    def extract_hits(self, blob):
        log.debug("Entering extract_hits()")
        if 'Hits' not in blob:
            log.error("No hits found in the blob!")
            return
        print(blob['Hits'])
        hits = self.geometry.apply(blob['Hits'])

        print("Number of hits: {0}".format(len(hits)))
        if self.min_tot:
            hits = hits[hits.tot > self.min_tot]
            print("Number of hits after ToT={0} cut: {1}".format(
                self.min_tot, len(hits)))
        if not self.min_tot and len(hits) > 500:
            print("Warning: consider applying a ToT filter to reduce the "
                  "amount of hits, according to your graphic cards "
                  "performance!")
        if len(hits) == 0:
            log.warning("No hits remaining after applying the ToT cut")
            return
        return hits.sorted(by='time')

    def add_neutrino(self, blob):
        """Add the neutrino to the scene."""
        if 'Neutrino' not in blob:
            return
        print(neutrino)
        pos = neutrino.pos
        particle = Neutrino(pos[0], pos[1], pos[2], neutrino.dir.x,
                            neutrino.dir.y, neutrino.dir.z, 0)
        particle.color = (1.0, 0.0, 0.0)
        particle.line_width = 3
        self.objects.setdefault("neutrinos", []).append(particle)

    def add_mc_tracks(self, blob):
        """Find MC particles and add them to the objects to render."""
        try:
            track_ins = blob['McTracks']
        except KeyError:
            print("No MCTracks found.")
            return

        event_info = blob['EventInfo']
        timestamp_in_ns = event_info.timestamp * 1e9 + event_info.nanoseconds

        from km3modules.mc import convert_mc_times_to_jte_times
        time_converter = np.frompyfunc(convert_mc_times_to_jte_times, 3, 1)
        track_ins['time'] = time_converter(track_ins.time, timestamp_in_ns,
                                           event_info.mc_time)

        # print(track_ins)

        # try:
        #     highest_energetic_track = max(track_ins, key=lambda t: t.E)
        #     # highest_energy = highest_energetic_track.E
        # except AttributeError:  # hdf5 mc tracks are not implemented yet
        #     highest_energetic_track = max(track_ins, key=lambda t: t.energy)
        #     # highest_energy = highest_energetic_track.energy

        for track in track_ins:
            particle_type = track.type
            energy = track.energy
            track_length = np.abs(track.length)
            print("Track length: {0}".format(track_length))
            if particle_type in (0, 22):  # skip unknowns, photons
                continue
#             if angle_between(highest_energetic_track.dir, track.dir) > 0.035:
#                 # TODO: make this realistic!
#                 # skip if angle too large
#                 continue
# #            if particle_type not in (-11, 11, -13, 13, -15, 15):
# #                # TODO: make this realistic!
# #                track_length = 200 * energy / highest_energy
            particle = Particle(
                track.pos_x,
                track.pos_y,
                track.pos_z,
                track.dir_x,
                track.dir_y,
                track.dir_z,
                track.time,
                constants.c,
                self.colourist,
                energy,
                length=track_length)
            particle.hidden = not self.show_secondaries
            # if track.id == highest_energetic_track.id:
            #     particle.color = (0.0, 1.0, 0.2)
            #     particle.line_width = 3
            #     particle.cherenkov_cone_enabled = True
            #     particle.hidden = False
            self.objects.setdefault("mc_tracks", []).append(particle)

    def add_reco_tracks(self, blob):
        """Find reco particles and add them to the objects to render."""
        pass
        # try:
        #     reco = blob['RecoTrack']
        # except (KeyError, TypeError):
        #     return
        # particle = ParticleFit(track.pos.x, track.pos.y, track.pos.z,
        #                        track.dir.x, track.dir.y, track.dir.z,
        #                        constants.c, track.ts, track.te)


#       dir = Direction((-0.05529533412, -0.1863083737, -0.9809340528))
#       pos = Position(( 128.9671546, 135.4618441, 397.8256624))
#       self.camera.target = Position(( 128.9671546, 135.4618441, 397.8256624))
#       # pos.z += 405.93
#       offset = 0
#       pos = pos + offset*dir
#       t_offset = offset / constants.c_water_km3net * 1e9
#       #t_0 = 86355000.1 - t_offset
#       t_0 = 86358182.1
#       print(t_offset)
#       print(t_0)
#       print(constants.c)
#       particle = Particle(pos.x, pos.y, pos.z,
#                              dir.x, dir.y, dir.z, t_0,
#                              constants.c, self.colourist, 1e4)
#       # particle.cherenkov_cone_enabled = True
# particle.hidden = False
# particle.line_width = 3
# self.objects.setdefault("reco_tracks", []).append(particle)

    def toggle_secondaries(self):
        self.show_secondaries = not self.show_secondaries

        secondaries = self.objects["mc_tracks"]
        for secondary in secondaries:
            secondary.hidden = not self.show_secondaries

        highest_energetic = max(secondaries, key=lambda s: s.energy)
        if highest_energetic:
            highest_energetic.hidden = False

    def load_next_blob(self):
        print("Loading next blob")
        try:
            self.load_blob(self.event_index + 1)
        except IndexError:
            return
        else:
            self.clock.reset()
            self.event_index += 1

    def load_previous_blob(self):
        try:
            self.load_blob(self.event_index - 1)
        except IndexError:
            return
        else:
            self.clock.reset()
            self.event_index -= 1

    def init_opengl(self, width, height, x, y):
        glutInit()
        glutInitWindowPosition(x, y)
        glutInitWindowSize(width, height)
        glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH
                            | GLUT_MULTISAMPLE)
        glutCreateWindow("Rainbow Alga")
        glutDisplayFunc(self.render)
        glutIdleFunc(self.render)
        glutReshapeFunc(self.resize)

        glutMouseFunc(self.mouse)
        glutMotionFunc(self.drag)
        glutKeyboardFunc(self.keyboard)
        glutSpecialFunc(self.special_keyboard)

        glClearDepth(1.0)
        glClearColor(0.0, 0.0, 0.0, 0.0)
        glMatrixMode(GL_PROJECTION)
        glLoadIdentity()
        glFrustum(-1.0, 1.0, -1.0, 1.0, 1.0, 3000)
        glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT)

        # Lighting
        light_ambient = (0.0, 0.0, 0.0, 1.0)
        light_diffuse = (1.0, 1.0, 1.0, 1.0)
        light_specular = (1.0, 1.0, 1.0, 1.0)
        light_position = (-100.0, 100.0, 100.0, 0.0)

        mat_ambient = (0.7, 0.7, 0.7, 1.0)
        mat_diffuse = (0.8, 0.8, 0.8, 1.0)
        mat_specular = (1.0, 1.0, 1.0, 1.0)
        high_shininess = (100)

        glEnable(GL_LIGHT0)
        glEnable(GL_NORMALIZE)
        glEnable(GL_COLOR_MATERIAL)
        glEnable(GL_LIGHTING)

        glLightfv(GL_LIGHT0, GL_AMBIENT, light_ambient)
        glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse)
        glLightfv(GL_LIGHT0, GL_SPECULAR, light_specular)
        glLightfv(GL_LIGHT0, GL_POSITION, light_position)

        glMaterialfv(GL_FRONT, GL_AMBIENT, mat_ambient)
        glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse)
        glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular)
        glMaterialfv(GL_FRONT, GL_SHININESS, high_shininess)

        # Transparency
        glEnable(GL_BLEND)
        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)

    def render(self):
        self.clock.record_frame_time()

        if self.is_recording and not self.timer.is_snoozed:
            self.frame_index += 1
            frame_name = "Frame_{0:05d}.jpg".format(self.frame_index)
            self.save_screenshot(frame_name)
            self.timer.snooze()

        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)

        self.colourist.now_background()

        if self.camera.is_rotating:
            self.camera.rotate_z(0.2)
        self.camera.look()

        self.draw_detector()

        glEnable(GL_DEPTH_TEST)
        glEnable(GL_LINE_SMOOTH)
        glShadeModel(GL_FLAT)
        glEnable(GL_LIGHTING)

        for obj in self.shaded_objects:
            obj.draw(self.clock.time, self.spectrum)

        glDisable(GL_LIGHTING)

        for obj in itertools.chain.from_iterable(self.objects.values()):
            obj.draw(self.clock.time)

        self.draw_gui()

        glutSwapBuffers()

    def draw_detector(self):
        glUseProgram(self.shader)
        try:
            self.dom_positions_vbo.bind()
            try:
                glEnableClientState(GL_VERTEX_ARRAY)
                glVertexPointerf(self.dom_positions_vbo)
                glPointSize(2)
                glDrawArrays(GL_POINTS, 0, len(self.dom_positions) * 3)
            finally:
                self.dom_positions_vbo.unbind()
                glDisableClientState(GL_VERTEX_ARRAY)
        finally:
            glUseProgram(0)

    def draw_gui(self):
        logo = self.logo
        logo_bytes = self.logo_bytes

        width = glutGet(GLUT_WINDOW_WIDTH)
        height = glutGet(GLUT_WINDOW_HEIGHT)
        glMatrixMode(GL_PROJECTION)
        glPushMatrix()
        glLoadIdentity()
        glOrtho(0.0, width, height, 0.0, -1.0, 10.0)
        glMatrixMode(GL_MODELVIEW)
        glLoadIdentity()
        glShadeModel(GL_SMOOTH)

        glClear(GL_DEPTH_BUFFER_BIT)

        try:
            self.draw_colour_legend()
        except TypeError:
            pass

        glPushMatrix()
        glLoadIdentity()
        glRasterPos(4, logo.size[1] + 4)
        glDrawPixels(logo.size[0], logo.size[1], GL_RGB, GL_UNSIGNED_BYTE,
                     logo_bytes)
        glPopMatrix()

        glMatrixMode(GL_PROJECTION)
        glPopMatrix()
        glMatrixMode(GL_MODELVIEW)

        self.colourist.now_text()

        if self.show_help:
            self.display_help()

        if self.show_info:
            self.display_info()

    def draw_colour_legend(self):
        menubar_height = self.logo.size[1] + 4
        width = glutGet(GLUT_WINDOW_WIDTH)
        height = glutGet(GLUT_WINDOW_HEIGHT)
        # Colour legend
        left_x = width - 20
        right_x = width - 10
        min_y = menubar_height + 5
        max_y = height - 20
        time_step_size = math.ceil(
            (self.max_hit_time - self.min_hit_time) / 20 / 50) * 50
        hit_times = list(
            range(
                int(self.min_hit_time), int(self.max_hit_time),
                int(time_step_size)))
        if len(hit_times) > 1:
            segment_height = int((max_y - min_y) / len(hit_times))
            glMatrixMode(GL_MODELVIEW)
            glLoadIdentity()
            glDisable(GL_LIGHTING)
            glBegin(GL_QUADS)
            for hit_time in hit_times:
                segment_nr = hit_times.index(hit_time)
                glColor3f(*self.spectrum(hit_time))
                glVertex2f(left_x, max_y - segment_height * segment_nr)
                glVertex2f(right_x, max_y - segment_height * segment_nr)
                glColor3f(*self.spectrum(hit_time + time_step_size))
                glVertex2f(left_x, max_y - segment_height * (segment_nr + 1))
                glVertex2f(right_x, max_y - segment_height * (segment_nr + 1))
            glEnd()

            # Colour legend labels
            self.colourist.now_text()
            for hit_time in hit_times:
                segment_nr = hit_times.index(hit_time)
                draw_text_2d(
                    "{0:>5}ns".format(int(hit_time - self.time_offset)),
                    width - 80, (height - max_y) + segment_height * segment_nr)

    def resize(self, width, height):
        if width < 400:
            glutReshapeWindow(400, height)
        if height < 300:
            glutReshapeWindow(width, 300)
        if height == 0:
            height = 1

        glViewport(0, 0, width, height)
        glMatrixMode(GL_PROJECTION)
        glLoadIdentity()
        gluPerspective(45.0, float(width) / float(height), 0.1, 10000.0)
        glMatrixMode(GL_MODELVIEW)

    def mouse(self, button, state, x, y):
        width = glutGet(GLUT_WINDOW_WIDTH)

        if button == GLUT_LEFT_BUTTON:
            if state == GLUT_DOWN:
                if x > width - 70:
                    self.drag_mode = 'spectrum'
                else:
                    self.drag_mode = 'rotate'
                    self.camera.is_rotating = False
                self.mouse_x = x
                self.mouse_y = y
            if state == GLUT_UP:
                self.drag_mode = None
        if button == 3:
            self.camera.distance = self.camera.distance + 2
        if button == 4:
            self.camera.distance = self.camera.distance - 2

    def keyboard(self, key, x, y):
        log.debug("Key {} pressed".format(key))
        if (key == b"r"):
            self.clock.reset()
        if (key == b"h"):
            self.show_help = not self.show_help
        if (key == b'i'):
            self.show_info = not self.show_info
        if (key == b"+"):
            self.camera.distance = self.camera.distance - 50
        if (key == b"-"):
            self.camera.distance = self.camera.distance + 50
        if (key == b"."):
            self.min_tot += 0.5
            self.reload_blob()
        if (key == b","):
            self.min_tot -= 0.5
            self.reload_blob()
        if (key == b'n'):
            self.load_next_blob()
        if (key == b'p'):
            self.load_previous_blob()
        if (key == b'u'):
            self.toggle_secondaries()
        if (key == b't'):
            self.toggle_spectrum()
        if (key == b'x'):
            self.cmap = self.colourist.next_cmap
        if (key == b'm'):
            self.colourist.print_mode = not self.colourist.print_mode
            self.load_logo()
        if (key == b'a'):
            self.camera.is_rotating = not self.camera.is_rotating
        if (key == b'c'):
            self.colourist.cherenkov_cone_enabled = \
                not self.colourist.cherenkov_cone_enabled
        if (key == b"s"):
            event_number = self.blob['start_event'][0]
            try:
                neutrino = self.blob['Neutrino']
            except KeyError:
                neutrino_str = ''
            else:
                neutrino_str = str(neutrino).replace(' ', '_').replace(',', '')
                neutrino_str = neutrino_str.replace('Neutrino:', '')
            screenshot_name = "RA_Event{0}_ToTCut{1}{2}_t{3}ns.png".format(
                event_number, self.min_tot, neutrino_str, int(self.clock.time))

            self.save_screenshot(screenshot_name)
        if (key == b'v'):
            self.frame_index = 0
            self.is_recording = not self.is_recording
        if (key == b" "):
            if self.clock.is_paused:
                self.clock.resume()
            else:
                self.clock.pause()
        if (key in (b'q', b'\x1b')):
            raise SystemExit

    def special_keyboard(self, key, x, z):
        if key == GLUT_KEY_LEFT:
            self.clock.rewind(300)
        if key == GLUT_KEY_RIGHT:
            self.clock.fast_forward(300)

    def drag(self, x, y):
        if self.drag_mode == 'rotate':
            self.camera.rotate_z(self.mouse_x - x)
            self.camera.move_z(-(self.mouse_y - y) * 8)
        if self.drag_mode == 'spectrum':
            self.min_hit_time += (self.mouse_y - y) * 10
            self.max_hit_time += (self.mouse_y - y) * 10
            self.max_hit_time -= (self.mouse_x - x) * 10
            self.min_hit_time += (self.mouse_x - x) * 10
            self.min_hit_time = base_round(self.min_hit_time, 10)
            self.max_hit_time = base_round(self.max_hit_time, 10)
        self.mouse_x = x
        self.mouse_y = y

    def save_screenshot(self, name='screenshot.png'):
        width = glutGet(GLUT_WINDOW_WIDTH)
        height = glutGet(GLUT_WINDOW_HEIGHT)
        pixelset = (GLubyte * (3 * width * height))(0)
        glReadPixels(0, 0, width, height, GL_RGB, GL_UNSIGNED_BYTE, pixelset)
        image = Image.frombytes(
            mode="RGB", size=(width, height), data=pixelset)
        image = image.transpose(Image.FLIP_TOP_BOTTOM)
        image.save(name)
        print("Screenshot saved as '{0}'.".format(name))

    @property
    def help_string(self):
        if not self._help_string:
            options = {
                'h': 'help',
                'i': 'show event info',
                'n': 'next event',
                'p': 'previous event',
                'LEFT': '+100ns',
                'RIGHT': '-100ns',
                'a': 'enable/disable rotation animation',
                'c': 'enable/disable Cherenkov cone',
                't': 'toggle between spectra',
                'u': 'toggle secondaries',
                'x': 'cycle through colour schemes',
                'm': 'toggle screen/print mode',
                's': 'save screenshot (screenshot.png)',
                'v': 'start/stop recording (Frame_XXXXX.jpg)',
                'r': 'reset time',
                '<space>': 'pause time',
                '+ or -': 'zoom in/out',
                ', or .': 'decrease/increase min_tot by 0.5ns',
                '<esc> or q': 'quit',
            }
            help_string = "Keyboard commands:\n-------------------\n"
            for key in sorted(options.keys()):
                help_string += "{key:>10} : {description}\n" \
                               .format(key=key, description=options[key])
            self._help_string = help_string
        return self._help_string

    @property
    def blob_info(self):
        if not self.blob:
            return ''
        info_text = ''
        if 'start_event' in self.blob:
            event_number = self.blob['start_event'][0]
            info_text += "Event #{0}, ToT>{1}ns\n" \
                         .format(event_number, self.min_tot)
        if 'Neutrion' in self.blob:
            neutrino = self.blob['Neutrino']
            info_text += str(neutrino)

        return info_text

    def display_help(self):
        pos_y = glutGet(GLUT_WINDOW_HEIGHT) - 80
        draw_text_2d(self.help_string, 10, pos_y)

    def display_info(self):
        draw_text_2d(
            "FPS:  {0:.1f}\nTime: {1:.0f} (+{2:.0f}) ns".format(
                self.clock.fps, self.clock.time - self.time_offset,
                self.time_offset), 10, 30)
        draw_text_2d(self.blob_info, 150, 30)
示例#32
0
 def test_comments_are_written(self):
     det = Detector(filename=data_path("detx/detx_v3.detx"))
     det.add_comment("foo")
     assert 3 == len(det.comments)
     assert det.comments[2] == "foo"
     assert "# foo" == det.ascii.splitlines()[2]
示例#33
0
 def test_detx_v3_is_the_same_ascii(self):
     det = Detector(filename=data_path("detx/detx_v3.detx"))
     with open(data_path("detx/detx_v3.detx"), "r") as fobj:
         assert fobj.read() == det.ascii
示例#34
0
class TestDetector(TestCase):

    def setUp(self):
        self.det = Detector()
        self.det.det_file = EXAMPLE_DETX

    def test_parse_header_extracts_correct_det_id(self):
        self.det.parse_header()
        self.assertEqual(1, self.det.det_id)

    def test_parse_header_extracts_correct_n_doms(self):
        self.det.parse_header()
        self.assertEqual(3, self.det.n_doms)

    def test_parse_doms_maps_each_dom_correctly(self):
        self.det.parse_doms()
        expected = {1: (1, 1, 3), 2: (1, 2, 3), 3: (1, 3, 3)}
        self.assertDictEqual(expected, self.det.doms)

    def test_parse_doms_maps_each_dom_correctly_for_mixed_pmt_ids(self):
        self.det.det_file = EXAMPLE_DETX_MIXED_IDS
        self.det.parse_doms()
        expected = {8: (1, 1, 3), 7: (1, 2, 3), 6: (1, 3, 3)}
        self.assertDictEqual(expected, self.det.doms)

    @skipIf(True, "Weird one hour bias on date?")
    def test_parse_doms_fills_pmts_dict(self):
        self.det.parse_doms()
        self.assertEqual(9, len(self.det.pmts))
        self.assertTupleEqual((7, 3.1, 3.2, 3.3, -1.1, 0.2, 0.3, 70),
                              self.det.pmts[(1, 3, 0)])

    def test_dom_positions(self):
        self.det.parse_doms()
        for i, position in enumerate(self.det.dom_positions):
            self.assertAlmostEqual(i + 1.1, position.x)
            self.assertAlmostEqual(i + 1.2, position.y)
            self.assertAlmostEqual(i + 1.3, position.z)

    def test_omkeys(self):
        self.det.parse_doms()
        self.assertEqual((1, 1, 0), self.det.pmt_with_id(1).omkey)
        self.assertEqual((1, 2, 1), self.det.pmt_with_id(5).omkey)

    def test_pmt_with_id_raises_exception_for_invalid_id(self):
        self.det.parse_doms()
        with self.assertRaises(KeyError):
            self.det.pmt_with_id(100)

    @skipIf(True, "DOM positions ordering unclear")
    def test_dom_positions_with_mixed_pmt_ids(self):
        self.det.det_file = EXAMPLE_DETX_MIXED_IDS
        self.det.parse_doms()
        for i, position in enumerate(self.det.dom_positions):
            self.assertAlmostEqual(i + 1.1, position.x)
            self.assertAlmostEqual(i + 1.2, position.y)
            self.assertAlmostEqual(i + 1.3, position.z)

    @skipIf(True, "DOM ordering is probably not important!")
    def test_ascii_detector(self):
        self.det.det_file = EXAMPLE_MC_DETX_WRITE_MIXED_IDS
        self.det.parse_header()
        self.det.parse_doms()
        self.assertEqual(self.det.det_file.getvalue(), self.det.ascii)

    def test_pmtid2omkey_old(self):
        pmtid2omkey = self.det.pmtid2omkey_old
        self.assertEqual((1, 13, 12), tuple(pmtid2omkey(168)))
        self.assertEqual((1, 12, 18), tuple(pmtid2omkey(205)))
        self.assertEqual((1, 11, 22), tuple(pmtid2omkey(240)))
        self.assertEqual((4, 11, 2), tuple(pmtid2omkey(1894)))
        self.assertEqual((9, 18, 0), tuple(pmtid2omkey(4465)))
        self.assertEqual((95, 7, 16), tuple(pmtid2omkey(52810)))
        self.assertEqual((95, 4, 13), tuple(pmtid2omkey(52900)))

    def test_pmtid2omkey_old_handles_floats(self):
        pmtid2omkey = self.det.pmtid2omkey_old
        self.assertEqual((1, 13, 12), tuple(pmtid2omkey(168.0)))
        self.assertEqual((1, 12, 18), tuple(pmtid2omkey(205.0)))
        self.assertEqual((1, 11, 22), tuple(pmtid2omkey(240.0)))
        self.assertEqual((4, 11, 2), tuple(pmtid2omkey(1894.0)))
        self.assertEqual((9, 18, 0), tuple(pmtid2omkey(4465.0)))
        self.assertEqual((95, 7, 16), tuple(pmtid2omkey(52810.0)))
        self.assertEqual((95, 4, 13), tuple(pmtid2omkey(52900.0)))
示例#35
0
    def test_center_of_mass_with_another_detx(self):
        det = Detector()
        det._det_file = EXAMPLE_DETX_RADIAL
        det._parse_doms()

        assert np.allclose([-0.2, 0., 0.2], det.com)
示例#36
0
    def test_center_of_mass(self):
        det = Detector()
        det._det_file = EXAMPLE_DETX
        det._parse_doms()

        assert np.allclose([2.4, 2.5, 2.6], det.com)
示例#37
0
import numpy as np
from scipy.spatial import ConvexHull
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D  # noqa
from km3net_testdata import data_path

from km3pipe.hardware import Detector
from km3pipe.math import Polygon
import km3pipe.style

km3pipe.style.use("km3pipe")

detx = data_path(
    "detx/orca_115strings_av23min20mhorizontal_18OMs_alt9mvertical_v1.detx")
detector = Detector(detx)
xy = detector.xy_positions
hull = ConvexHull(xy)

##############################################################################
# Plot it:

plt.plot(xy[:, 0], xy[:, 1], "o")
for simplex in hull.simplices:
    plt.plot(xy[simplex, 0], xy[simplex, 1], "k-")

##############################################################################
# We could also have directly used the vertices of the hull, which
# for 2-D are guaranteed to be in counterclockwise order:

plt.plot(xy[hull.vertices, 0], xy[hull.vertices, 1], "r--", lw=2)
示例#38
0
class TestDetector(TestCase):
    def setUp(self):
        self.det = Detector()
        self.det._det_file = EXAMPLE_DETX

    def test_parse_header_extracts_correct_det_id(self):
        self.det._parse_header()
        self.assertEqual(1, self.det.det_id)

    def test_parse_header_extracts_correct_n_doms(self):
        self.det._parse_header()
        self.assertEqual(3, self.det.n_doms)

    def test_parse_doms_maps_each_dom_correctly(self):
        self.det._parse_doms()
        expected = {1: (1, 1, 3), 2: (1, 2, 3), 3: (1, 3, 3)}
        self.assertDictEqual(expected, self.det.doms)

    def test_dom_ids(self):
        self.det._parse_doms()
        self.assertEqual((1, 2, 3), tuple(self.det.dom_ids))

    def test_parse_reset_cache(self):
        self.det._parse_doms()
        assert not self.det._dom_positions
        assert not self.det._pmt_angles
        assert not self.det._xy_positions
        self.det.dom_positions
        self.det.pmt_angles
        self.det.xy_positions
        assert self.det._dom_positions
        assert len(self.det._pmt_angles) == 3
        assert len(self.det._xy_positions) == 1
        self.det.reset_caches()
        assert not self.det._dom_positions
        assert not self.det._pmt_angles
        assert not self.det._xy_positions

    def test_parse_doms_maps_each_dom_correctly_for_mixed_pmt_ids(self):
        self.det._det_file = EXAMPLE_DETX_MIXED_IDS
        self.det._parse_doms()
        expected = {8: (1, 1, 3), 7: (1, 2, 3), 6: (1, 3, 3)}
        self.assertDictEqual(expected, self.det.doms)

    def test_dom_positions(self):
        self.det._parse_doms()
        assert np.allclose([1.49992331, 1.51893187, 1.44185513],
                           self.det.dom_positions[1])
        assert np.allclose([2.49992331, 2.51893187, 2.44185513],
                           self.det.dom_positions[2])
        assert np.allclose([3.49992331, 3.51893187, 3.44185513],
                           self.det.dom_positions[3])

    def test_xy_positions(self):
        self.det._parse_doms()
        assert len(self.det.xy_positions) == 1
        assert np.allclose([1.49992331, 1.51893187], self.det.xy_positions[0])

    def test_correct_number_of_pmts(self):
        self.det._parse_doms()
        assert 9 == len(self.det.pmts)

    def test_pmt_attributes(self):
        self.det._parse_doms()
        assert (1, 2, 3, 4, 5, 6, 7, 8, 9) == tuple(self.det.pmts.pmt_id)
        assert np.allclose([1.1, 1.4, 1.7, 2.1, 2.4, 2.7, 3.1, 3.4, 3.7],
                           self.det.pmts.pos_x)
        assert np.allclose((1.7, 1.8, 1.9), self.det.pmts.pos[2])
        assert np.allclose((0.1, 0.2, -1.3), self.det.pmts.dir[8])

    def test_pmt_index_by_omkey(self):
        self.det._parse_doms()
        assert 5 == self.det._pmt_index_by_omkey[(1, 2, 2)]
        assert 0 == self.det._pmt_index_by_omkey[(1, 1, 0)]
        assert 4 == self.det._pmt_index_by_omkey[(1, 2, 1)]
        assert 1 == self.det._pmt_index_by_omkey[(1, 1, 1)]

    def test_pmt_index_by_pmt_id(self):
        self.det._parse_doms()
        assert 0 == self.det._pmt_index_by_pmt_id[1]

    def test_pmt_with_id_returns_correct_omkeys(self):
        self.det._parse_doms()
        pmt = self.det.pmt_with_id(1)
        assert (1, 1, 0) == (pmt.du, pmt.floor, pmt.channel_id)
        pmt = self.det.pmt_with_id(5)
        assert (1, 2, 1) == (pmt.du, pmt.floor, pmt.channel_id)

    def test_pmt_with_id_returns_correct_omkeys_with_mixed_pmt_ids(self):
        self.det._det_file = EXAMPLE_DETX_MIXED_IDS
        self.det._parse_doms()
        pmt = self.det.pmt_with_id(73)
        assert (1, 2, 1) == (pmt.du, pmt.floor, pmt.channel_id)
        pmt = self.det.pmt_with_id(81)
        assert (1, 1, 1) == (pmt.du, pmt.floor, pmt.channel_id)

    def test_pmt_with_id_raises_exception_for_invalid_id(self):
        self.det._parse_doms()
        with self.assertRaises(KeyError):
            self.det.pmt_with_id(100)

    def test_get_pmt(self):
        self.det._det_file = EXAMPLE_DETX_MIXED_IDS
        self.det._parse_doms()
        pmt = self.det.get_pmt(7, 2)
        assert (1, 2, 2) == (pmt.du, pmt.floor, pmt.channel_id)

    def test_xy_pos(self):
        self.det._parse_doms()
        xy = self.det.xy_positions
        assert xy is not None

    def test_ascii(self):
        detx_string = "\n".join((
            "1 3",
            "1 1 1 3",
            " 1 1.1 1.2 1.3 1.1 2.1 3.1 10.0",
            " 2 1.4 1.5 1.6 4.1 5.1 6.1 20.0",
            " 3 1.7 1.8 1.9 7.1 8.1 9.1 30.0",
            "2 1 2 3",
            " 4 2.1 2.2 2.3 1.2 2.2 3.2 40.0",
            " 5 2.4 2.5 2.6 4.2 5.2 6.2 50.0",
            " 6 2.7 2.8 2.9 7.2 8.2 9.2 60.0",
            "3 1 3 3",
            " 7 3.1 3.2 3.3 1.3 2.3 3.3 70.0",
            " 8 3.4 3.5 3.6 4.3 5.3 6.3 80.0",
            " 9 3.7 3.8 3.9 7.3 8.3 9.3 90.0\n",
        ))
        detx_fob = StringIO(detx_string)

        self.det = Detector()
        self.det._det_file = detx_fob
        self.det._parse_header()
        self.det._parse_doms()
        assert detx_string == self.det.ascii

    def test_ascii_with_mixed_dom_ids(self):
        detx_string = "\n".join((
            "1 3",
            "8 1 1 3",
            " 1 1.1 1.2 1.3 1.1 2.1 3.1 10.0",
            " 2 1.4 1.5 1.6 4.1 5.1 6.1 20.0",
            " 3 1.7 1.8 1.9 7.1 8.1 9.1 30.0",
            "4 1 2 3",
            " 4 2.1 2.2 2.3 1.2 2.2 3.2 40.0",
            " 5 2.4 2.5 2.6 4.2 5.2 6.2 50.0",
            " 6 2.7 2.8 2.9 7.2 8.2 9.2 60.0",
            "9 1 3 3",
            " 7 3.1 3.2 3.3 1.3 2.3 3.3 70.0",
            " 8 3.4 3.5 3.6 4.3 5.3 6.3 80.0",
            " 9 3.7 3.8 3.9 7.3 8.3 9.3 90.0\n",
        ))
        detx_fobj = StringIO(detx_string)

        self.det = Detector()
        self.det._det_file = detx_fobj
        self.det._parse_header()
        self.det._parse_doms()
        assert detx_string == self.det.ascii

    def test_detx_format_version_1(self):
        det = Detector(filename=join(TEST_DATA_DIR, 'detx_v1.detx'))
        assert 2 == det.n_dus
        assert 6 == det.n_doms
        assert 3 == det.n_pmts_per_dom
        assert 'v1' == det.version
        self.assertListEqual([1.1, 1.2, 1.3], list(det.pmts.pos[0]))
        self.assertListEqual([3.4, 3.5, 3.6], list(det.pmts.pos[7]))
        self.assertListEqual([23.4, 23.5, 23.6], list(det.pmts.pos[16]))

    def test_detx_v1_is_the_same_ascii(self):
        det = Detector(filename=join(TEST_DATA_DIR, 'detx_v1.detx'))
        with open(join(TEST_DATA_DIR, 'detx_v1.detx'), 'r') as fobj:
            assert fobj.read() == det.ascii

    def test_detx_format_version_2(self):
        det = Detector(filename=join(TEST_DATA_DIR, 'detx_v2.detx'))
        assert 2 == det.n_dus
        assert 6 == det.n_doms
        assert 3 == det.n_pmts_per_dom
        assert 256500.0 == det.utm_info.easting
        assert 4743000.0 == det.utm_info.northing
        assert 'WGS84' == det.utm_info.ellipsoid
        assert '32N' == det.utm_info.grid
        assert -2425.0 == det.utm_info.z
        assert 1500000000.1 == det.valid_from
        assert 9999999999.0 == det.valid_until
        assert 'v2' == det.version
        self.assertListEqual([1.1, 1.2, 1.3], list(det.pmts.pos[0]))
        self.assertListEqual([3.4, 3.5, 3.6], list(det.pmts.pos[7]))
        self.assertListEqual([23.4, 23.5, 23.6], list(det.pmts.pos[16]))

    def test_detx_v2_is_the_same_ascii(self):
        det = Detector(filename=join(TEST_DATA_DIR, 'detx_v2.detx'))
        with open(join(TEST_DATA_DIR, 'detx_v2.detx'), 'r') as fobj:
            assert fobj.read() == det.ascii

    def test_detx_format_version_3(self):
        det = Detector(filename=join(TEST_DATA_DIR, 'detx_v3.detx'))
        assert 2 == det.n_dus
        assert 6 == det.n_doms
        assert 3 == det.n_pmts_per_dom
        assert 256500.0 == det.utm_info.easting
        assert 4743000.0 == det.utm_info.northing
        assert 'WGS84' == det.utm_info.ellipsoid
        assert '32N' == det.utm_info.grid
        assert -2425.0 == det.utm_info.z
        assert 1500000000.1 == det.valid_from
        assert 9999999999.0 == det.valid_until
        assert 'v3' == det.version
        self.assertListEqual([1.1, 1.2, 1.3], list(det.pmts.pos[0]))
        self.assertListEqual([3.4, 3.5, 3.6], list(det.pmts.pos[7]))
        self.assertListEqual([23.4, 23.5, 23.6], list(det.pmts.pos[16]))

    def test_detector_repr(self):
        det = Detector(filename=join(TEST_DATA_DIR, 'detx_v3.detx'))
        assert "Detector id: '23', n_doms: 6, dus: [1, 2]" == repr(det)

    def test_detx_format_version_3_with_whitespace(self):
        det = Detector(filename=join(TEST_DATA_DIR, 'detx_v3_whitespace.detx'))
        assert 2 == det.n_dus
        assert 6 == det.n_doms
        assert 3 == det.n_pmts_per_dom
        assert 256500.0 == det.utm_info.easting
        assert 4743000.0 == det.utm_info.northing
        assert 'WGS84' == det.utm_info.ellipsoid
        assert '32N' == det.utm_info.grid
        assert -2425.0 == det.utm_info.z
        assert 1500000000.1 == det.valid_from
        assert 9999999999.0 == det.valid_until
        assert 'v3' == det.version
        self.assertListEqual([1.1, 1.2, 1.3], list(det.pmts.pos[0]))
        self.assertListEqual([3.4, 3.5, 3.6], list(det.pmts.pos[7]))
        self.assertListEqual([23.4, 23.5, 23.6], list(det.pmts.pos[16]))

    def test_detx_format_comments(self):
        det = Detector(filename=join(TEST_DATA_DIR, 'detx_v1.detx'))
        assert len(det.comments) == 0

        det = Detector(filename=join(TEST_DATA_DIR, 'detx_v2.detx'))
        assert len(det.comments) == 0

        det = Detector(filename=join(TEST_DATA_DIR, 'detx_v3.detx'))
        assert len(det.comments) == 2
        assert " a comment line" == det.comments[0]
        assert " another comment line starting with '#'" == det.comments[1]

    def test_comments_are_written(self):
        det = Detector(filename=join(TEST_DATA_DIR, 'detx_v3.detx'))
        det.add_comment("foo")
        assert 3 == len(det.comments)
        assert det.comments[2] == "foo"
        assert "# foo" == det.ascii.splitlines()[2]

    def test_detx_v3_is_the_same_ascii(self):
        det = Detector(filename=join(TEST_DATA_DIR, 'detx_v3.detx'))
        with open(join(TEST_DATA_DIR, 'detx_v3.detx'), 'r') as fobj:
            assert fobj.read() == det.ascii

    def test_translate_detector(self):
        self.det._parse_doms()
        t_vec = np.array([1, 2, 3])
        orig_pos = self.det.pmts.pos.copy()
        self.det.translate_detector(t_vec)
        assert np.allclose(orig_pos + t_vec, self.det.pmts.pos)

    def test_translate_detector_updates_xy_positions(self):
        self.det._parse_doms()
        t_vec = np.array([1, 2, 3])
        orig_xy_pos = self.det.xy_positions.copy()
        self.det.translate_detector(t_vec)
        assert np.allclose(orig_xy_pos + t_vec[:2], self.det.xy_positions)

    def test_translate_detector_updates_dom_positions(self):
        self.det._parse_doms()
        t_vec = np.array([1, 2, 3])
        orig_dom_pos = deepcopy(self.det.dom_positions)
        self.det.translate_detector(t_vec)
        for dom_id, pos in self.det.dom_positions.items():
            assert np.allclose(orig_dom_pos[dom_id] + t_vec, pos)

    def test_rotate_dom_by_yaw(self):
        det = Detector()
        det._det_file = EXAMPLE_DETX_RADIAL
        det._parse_doms()
        # here, only one PMT is checked
        dom_id = 1
        heading = 23
        channel_id = 0
        pmt_dir = det.pmts[det.pmts.dom_id == dom_id].dir[channel_id].copy()
        pmt_dir_rot = qrot_yaw(pmt_dir, heading)
        det.rotate_dom_by_yaw(dom_id, heading)
        assert np.allclose(
            pmt_dir_rot, det.pmts[det.pmts.dom_id == dom_id].dir[channel_id]
        )
        assert np.allclose([0.92050485, 0.39073113, 0],
                           det.pmts[det.pmts.dom_id == dom_id].pos[channel_id])

    def test_rotate_dom_set_by_step_by_360_degrees(self):
        det = Detector()
        det._det_file = EXAMPLE_DETX_RADIAL
        det._parse_doms()
        dom_id = 1
        channel_id = 0
        pmt_dir = det.pmts[det.pmts.dom_id == dom_id].dir[channel_id].copy()
        pmt_pos = det.pmts[det.pmts.dom_id == dom_id].pos[channel_id].copy()
        for i in range(36):
            det.rotate_dom_by_yaw(dom_id, 10)
        pmt_dir_rot = det.pmts[det.pmts.dom_id == dom_id].dir[channel_id]
        assert np.allclose(pmt_dir, pmt_dir_rot)
        pmt_pos_rot = det.pmts[det.pmts.dom_id == dom_id].pos[channel_id]
        assert np.allclose(pmt_pos, pmt_pos_rot)

    def test_rotate_du_by_yaw_step_by_step_360_degrees(self):
        det = Detector()
        det._det_file = EXAMPLE_DETX_RADIAL
        det._parse_doms()
        du = 2
        pmt_dir = det.pmts[det.pmts.du == du].dir.copy()
        pmt_pos = det.pmts[det.pmts.du == du].pos.copy()
        pmt_dir_other_dus = det.pmts[det.pmts.du != du].dir.copy()
        pmt_pos_other_dus = det.pmts[det.pmts.du != du].pos.copy()
        for i in range(36):
            det.rotate_du_by_yaw(du, 10)
        pmt_dir_rot = det.pmts[det.pmts.du == du].dir
        pmt_pos_rot = det.pmts[det.pmts.du == du].pos
        assert np.allclose(pmt_dir, pmt_dir_rot)
        assert np.allclose(pmt_pos, pmt_pos_rot)
        assert np.allclose(pmt_dir_other_dus, det.pmts[det.pmts.du != du].dir)
        assert np.allclose(pmt_pos_other_dus, det.pmts[det.pmts.du != du].pos)

    def test_rescale_detector(self):
        self.det._parse_doms()
        dom_positions = deepcopy(self.det.dom_positions)
        scale_factor = 2
        self.det.rescale(scale_factor)
        for dom_id, dom_pos in self.det.dom_positions.items():
            assert np.allclose(dom_pos, dom_positions[dom_id] * scale_factor)

    def test_dom_table(self):
        self.det._parse_doms()
        dt = self.det.dom_table
        assert 3 == len(dt)
        assert np.allclose([1, 2, 3], dt.dom_id)
        assert np.allclose([1, 1, 1], dt.du)
        assert np.allclose([1, 2, 3], dt.floor)
        assert np.allclose([1.49992331, 2.49992331, 3.49992331], dt.pos_x)
        assert np.allclose([1.51893187, 2.51893187, 3.51893187], dt.pos_y)
        assert np.allclose([1.44185513, 2.44185513, 3.44185513], dt.pos_z)

    def test_dom_table_with_another_detx(self):
        det = Detector()
        det._det_file = EXAMPLE_DETX_RADIAL
        det._parse_doms()

        dt = det.dom_table
        assert 4 == len(dt)
        assert np.allclose([1, 2, 3, 4], dt.dom_id)
        assert np.allclose([1, 1, 1, 2], dt.du)
        assert np.allclose([1, 2, 3, 1], dt.floor)
        assert np.allclose([0, 0, 0, 0], dt.pos_x)
        assert np.allclose([0, 0, 0, 0], dt.pos_y)
        assert np.allclose([0, 0, 0, 0], dt.pos_z)

    def test_center_of_mass(self):
        det = Detector()
        det._det_file = EXAMPLE_DETX
        det._parse_doms()

        assert np.allclose([2.4, 2.5, 2.6], det.com)

    def test_center_of_mass_with_another_detx(self):
        det = Detector()
        det._det_file = EXAMPLE_DETX_RADIAL
        det._parse_doms()

        assert np.allclose([-0.2, 0., 0.2], det.com)
示例#39
0
class TestDetectorTransformations(TestCase):
    def setUp(self):
        self.det = Detector()
        self.det._det_file = EXAMPLE_DETX

    def test_translate_detector(self):
        self.det._parse()
        t_vec = np.array([1, 2, 3])
        orig_pos = self.det.pmts.pos.copy()
        self.det.translate_detector(t_vec)
        assert np.allclose(orig_pos + t_vec, self.det.pmts.pos)

    def test_translate_detector_updates_xy_positions(self):
        self.det._parse()
        t_vec = np.array([1, 2, 3])
        orig_xy_pos = self.det.xy_positions.copy()
        self.det.translate_detector(t_vec)
        assert np.allclose(orig_xy_pos + t_vec[:2], self.det.xy_positions)

    def test_translate_detector_updates_dom_positions(self):
        self.det._parse()
        t_vec = np.array([1, 2, 3])
        orig_dom_pos = deepcopy(self.det.dom_positions)
        self.det.translate_detector(t_vec)
        for dom_id, pos in self.det.dom_positions.items():
            assert np.allclose(orig_dom_pos[dom_id] + t_vec, pos)

    def test_rotate_dom_by_yaw(self):
        det = Detector()
        det._det_file = EXAMPLE_DETX_RADIAL
        det._parse()
        # here, only one PMT is checked
        dom_id = 1
        heading = 23
        channel_id = 0
        pmt_dir = det.pmts[det.pmts.dom_id == dom_id].dir[channel_id].copy()
        pmt_dir_rot = qrot_yaw(pmt_dir, heading)
        det.rotate_dom_by_yaw(dom_id, heading)
        assert np.allclose(pmt_dir_rot,
                           det.pmts[det.pmts.dom_id == dom_id].dir[channel_id])
        assert np.allclose(
            [0.92050485, 0.39073113, 0],
            det.pmts[det.pmts.dom_id == dom_id].pos[channel_id],
        )

    def test_rotate_dom_set_by_step_by_360_degrees(self):
        det = Detector()
        det._det_file = EXAMPLE_DETX_RADIAL
        det._parse()
        dom_id = 1
        channel_id = 0
        pmt_dir = det.pmts[det.pmts.dom_id == dom_id].dir[channel_id].copy()
        pmt_pos = det.pmts[det.pmts.dom_id == dom_id].pos[channel_id].copy()
        for i in range(36):
            det.rotate_dom_by_yaw(dom_id, 10)
        pmt_dir_rot = det.pmts[det.pmts.dom_id == dom_id].dir[channel_id]
        assert np.allclose(pmt_dir, pmt_dir_rot)
        pmt_pos_rot = det.pmts[det.pmts.dom_id == dom_id].pos[channel_id]
        assert np.allclose(pmt_pos, pmt_pos_rot)

    def test_rotate_du_by_yaw_step_by_step_360_degrees(self):
        det = Detector()
        det._det_file = EXAMPLE_DETX_RADIAL
        det._parse()
        du = 2
        pmt_dir = det.pmts[det.pmts.du == du].dir.copy()
        pmt_pos = det.pmts[det.pmts.du == du].pos.copy()
        pmt_dir_other_dus = det.pmts[det.pmts.du != du].dir.copy()
        pmt_pos_other_dus = det.pmts[det.pmts.du != du].pos.copy()
        for i in range(36):
            det.rotate_du_by_yaw(du, 10)
        pmt_dir_rot = det.pmts[det.pmts.du == du].dir
        pmt_pos_rot = det.pmts[det.pmts.du == du].pos
        assert np.allclose(pmt_dir, pmt_dir_rot)
        assert np.allclose(pmt_pos, pmt_pos_rot)
        assert np.allclose(pmt_dir_other_dus, det.pmts[det.pmts.du != du].dir)
        assert np.allclose(pmt_pos_other_dus, det.pmts[det.pmts.du != du].pos)

    def test_rescale_detector(self):
        self.det._parse()
        dom_positions = deepcopy(self.det.dom_positions)
        scale_factor = 2
        self.det.rescale(scale_factor)
        for dom_id, dom_pos in self.det.dom_positions.items():
            assert np.allclose(dom_pos, dom_positions[dom_id] * scale_factor)

    def test_dom_table(self):
        self.det._parse()
        dt = self.det.dom_table
        assert 3 == len(dt)
        assert np.allclose([1, 2, 3], dt.dom_id)
        assert np.allclose([1, 1, 1], dt.du)
        assert np.allclose([1, 2, 3], dt.floor)
        assert np.allclose([1.49992331, 2.49992331, 3.49992331], dt.pos_x)
        assert np.allclose([1.51893187, 2.51893187, 3.51893187], dt.pos_y)
        assert np.allclose([1.44185513, 2.44185513, 3.44185513], dt.pos_z)

    def test_dom_table_with_another_detx(self):
        det = Detector()
        det._det_file = EXAMPLE_DETX_RADIAL
        det._parse()

        dt = det.dom_table
        assert 4 == len(dt)
        assert np.allclose([1, 2, 3, 4], dt.dom_id)
        assert np.allclose([1, 1, 1, 2], dt.du)
        assert np.allclose([1, 2, 3, 1], dt.floor)
        assert np.allclose([0, 0, 0, 0], dt.pos_x)
        assert np.allclose([0, 0, 0, 0], dt.pos_y)
        assert np.allclose([0, 0, 0, 0], dt.pos_z)

    def test_center_of_mass(self):
        det = Detector()
        det._det_file = EXAMPLE_DETX
        det._parse()

        assert np.allclose([2.4, 2.5, 2.6], det.com)

    def test_center_of_mass_with_another_detx(self):
        det = Detector()
        det._det_file = EXAMPLE_DETX_RADIAL
        det._parse()

        assert np.allclose([-0.2, 0.0, 0.2], det.com)

    def test_jdetectordb_output_with_detx_v3(self):
        det = Detector(
            data_path(
                "detx/D_ORCA006_t.A02181836.p.A02181837.r.A02182001.detx"))
        assert det.utm_info is not None
        assert det.utm_info.ellipsoid == "WGS84"
        assert det.utm_info.grid == "32N"
        assert det.utm_info.easting == 256500.0
        assert det.utm_info.northing == 4743000.0
        assert det.utm_info.z == -2440.0
示例#40
0
 def test_init_with_detector(self):
     det = Detector(data_path("detx/detx_v1.detx"))
     Calibration(detector=det)
示例#41
0
import pandas as pd
import numpy as np

from km3pipe import Pipeline, Module
from km3pipe.hardware import Detector
from km3pipe.io import CHPump
from km3pipe.io.daq import DAQPreamble, DAQSummaryslice, DAQEvent
from km3pipe.time import tai_timestamp
import km3pipe.style

km3pipe.style.use('km3pipe')

PLOTS_PATH = '/home/km3net/monitoring/www/plots'
N_DOMS = 18
N_DUS = 2
detector = Detector(det_id=14)

xfmt = md.DateFormatter('%Y-%m-%d %H:%M')
lock = threading.Lock()


class DOMHits(Module):
    def configure(self):
        self.run = True
        self.max_events = 1000
        self.hits = deque(maxlen=1000)
        self.triggered_hits = deque(maxlen=1000)
        self.thread = threading.Thread(target=self.plot).start()

    def process(self, blob):
        tag = str(blob['CHPrefix'].tag)