Skip to content

Commit

Permalink
Refactor Penthesilea and Dorothea
Browse files Browse the repository at this point in the history
This PR simplifies and improves a few of our cities and base cities. Replaces the IC exceptions with NotImplementedErrore. Dorothea and Penthesilea have a lot in common and their event loops showed it. This PR squashes redundancies into a more versatile PCity. Penthesilea and Dorothea now need only worry themselves with setting writers and passing them their specific dst_event which are then used by PCity's event loop
  • Loading branch information
jjgomezcadenas committed Sep 14, 2017
2 parents 2222be0 + eb460d5 commit eb903c7
Show file tree
Hide file tree
Showing 8 changed files with 117 additions and 177 deletions.
94 changes: 87 additions & 7 deletions invisible_cities/cities/base_cities.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,6 @@
from .. core.exceptions import NoInputFiles
from .. core.exceptions import NoOutputFile
from .. core.exceptions import UnknownRWF
from .. core.exceptions import FileLoopMethodNotSet
from .. core.exceptions import EventLoopMethodNotSet
from .. core.exceptions import SipmEmptyList
from .. core.exceptions import SipmZeroCharge
from .. core.exceptions import ClusterEmptyList
Expand Down Expand Up @@ -81,6 +79,10 @@
from .. types.ic_types import NN
from .. types.ic_types import xy

from .. filters.s1s2_filter import s1s2_filter
from .. filters.s1s2_filter import s2si_filter
from .. filters.s1s2_filter import S12Selector

from .. daemons.idaemon import invoke_daemon

from typing import Sequence
Expand Down Expand Up @@ -253,19 +255,19 @@ def display_IO_info(self):

def file_loop(self):
"""Must be implemented by cities"""
raise FileLoopMethodNotSet
raise NotImplementedError("Concrete City must implement `file_loop`")

def event_loop(self):
"""Must be implemented by cities"""
raise EventLoopMethodNotSet
raise NotImplementedError("Concrete City must implement `event_loop`")

def write_parameters(self, h5out):
"""Must be implemented by cities"""
pass
raise NotImplementedError("Concrete City must implement `write_parameters`")

def get_writers(self, h5out):
"""Must be implemented by cities"""
pass
raise NotImplementedError("Concrete City must implement `get_writers`")

def set_up_database(self):
DataPMT = load_db.DataPMT (self.run_number)
Expand Down Expand Up @@ -624,13 +626,69 @@ def __init__(self, **kwds):


class PCity(City):
"""A PCity reads PMAPS. Consequently it provides a file loop
"""A PCity reads PMAPS. Consequently it provides a file loop and an event loop
that access and serves to the event_loop the corresponding PMAPS
vectors.
"""

def __init__(self, **kwds):
super().__init__(**kwds)
self.drift_v = self.conf.drift_v
self.s1s2_selector = S12Selector(**kwds)

self.cnt.init(n_events_tot = 0,
n_events_not_s1 = 0,
n_events_not_s2 = 0,
n_events_not_s2si = 0,
n_events_not_s1s2_filter = 0,
n_events_not_s2si_filter = 0,
n_events_selected = 0)

def create_dst_event(self, pmapVectors):
"""Must be implemented by any city derived from PCity"""
raise NotImplementedError("Concrete City must implement `create_dst_event`")


def event_loop(self, pmapVectors):
"""actions:
1. loops over all PMAPS
2. filter pmaps
3. write dst_event
"""

write_dst = self.writers
event_numbers= pmapVectors.events
timestamps = pmapVectors.timestamps
s1_dict = pmapVectors.s1
s2_dict = pmapVectors.s2
s2si_dict = pmapVectors.s2si

for evt_number, evt_time in zip(event_numbers, timestamps):
self.conditional_print(self.cnt.n_events_tot, self.cnt.n_events_selected)

# Count events in and break if necessary before filtering
what_next = self.event_range_step()
if what_next is EventLoop.skip_this_event: continue
if what_next is EventLoop.terminate_loop : break
self.cnt.n_events_tot += 1
# get pmaps
s1, s2, s2si = self. get_pmaps_from_dicts(s1_dict,
s2_dict,
s2si_dict,
evt_number)
# filtering
pass_filter = self.filter_event(s1, s2, s2si)
if not pass_filter:
continue
# event passed selection:
self.cnt.n_events_selected += 1

# create DST event & write to file
pmapVectors = PmapVectors(s1=s1, s2=s2, s2si=s2si,
events=evt_number,
timestamps=evt_time)
evt = self.create_dst_event(pmapVectors)
write_dst(evt)

def file_loop(self):
"""
Expand All @@ -657,6 +715,28 @@ def file_loop(self):

self.event_loop(pmapVectors)

def filter_event(self, s1, s2, s2si):
"""Filter the event in terms of s1, s2, s2si"""
# loop event away if any signal (s1, s2 or s2si) not present
if s1 == None:
self.cnt.n_events_not_s1 += 1
return False
elif s2 == None:
self.cnt.n_events_not_s2 += 1
return False
elif s2si == None:
self.cnt.n_events_not_s2si += 1
return False
# filters in s12 and s2si
f1 = s1s2_filter(self.s1s2_selector, s1, s2, s2si)
if not f1:
self.cnt.n_events_not_s1s2_filter += 1
return False
f2 = s2si_filter(s2si)
if not f2:
self.cnt.n_events_not_s2si_filter += 1
return False
return True

class KrCity(PCity):
"""A city that read pmaps and computes/writes a KrEvent"""
Expand Down
96 changes: 12 additions & 84 deletions invisible_cities/cities/dorothea.py
Original file line number Diff line number Diff line change
@@ -1,99 +1,27 @@
"""
code: dorothea.py
description: create a lightweight DST.
description: create a KDST.
credits: see ic_authors_and_legal.rst in /doc
last revised: JJGC, July-2017
last revised: JJGC, September-2017
"""

import numpy as np
import tables as tb

from .. core.configure import configure
from .. core.system_of_units_c import units

from .. io.kdst_io import kr_writer
from .. evm.ic_containers import PmapVectors

from .. reco import tbl_functions as tbl
from .. reco import pmaps_functions_c as pmp

from .. filters.s1s2_filter import s1s2_filter
from .. filters.s1s2_filter import S12Selector

from . base_cities import KrCity
from . base_cities import EventLoop

from .. io.kdst_io import kr_writer
from . base_cities import KrCity

class Dorothea(KrCity):
"""Read PMAPS and produces a KDST"""

def __init__(self, **kwds):
super().__init__(**kwds)

self.cnt.init(n_events_tot = 0,
nevt_out = 0,
n_events_not_s1 = 0,
n_events_not_s2 = 0,
n_events_not_s2si = 0,
n_events_rejected_filter = 0,
n_events_more_than_1_cluster = 0)


self.drift_v = self.conf.drift_v
self._s1s2_selector = S12Selector(**kwds)


def event_loop(self, pmapVectors):
"""actions:
1. loops over all PMAPS
2. filter pmaps
3. write kr_event
"""

write_kr = self.writers
event_numbers= pmapVectors.events
timestamps = pmapVectors.timestamps
s1_dict = pmapVectors.s1
s2_dict = pmapVectors.s2
s2si_dict = pmapVectors.s2si

for evt_number, evt_time in zip(event_numbers, timestamps):
self.conditional_print(self.cnt.n_events_tot, self.cnt.nevt_out)

# Count events in and break if necessary before filtering
what_next = self.event_range_step()
if what_next is EventLoop.skip_this_event: continue
if what_next is EventLoop.terminate_loop : break
self.cnt.n_events_tot += 1
# get pmaps
s1, s2, s2si = self. get_pmaps_from_dicts(s1_dict,
s2_dict,
s2si_dict,
evt_number)
# filtering
# loop event away if any signal (s1, s2 or s2si) not present
if s1 == None:
self.cnt.n_events_not_s1 += 1
continue
if s2 == None:
self.cnt.n_events_not_s2 += 1
continue
if s2si == None:
self.cnt.n_events_not_s2si += 1
continue
# loop event away if filter fails
if not s1s2_filter(self._s1s2_selector, s1, s2, s2si):
self.cnt.n_events_more_than_1_cluster += 1
continue
# event passed selection:
self.cnt.nevt_out += 1
# create Kr event & write to file
pmapVectors = PmapVectors(s1=s1, s2=s2, s2si=s2si,
events=evt_number,
timestamps=evt_time)
evt = self.create_kr_event(pmapVectors)
write_kr(evt)

def get_writers(self, h5out):
"""Get the writers needed by dorothea"""
return kr_writer(h5out)

def create_dst_event(self, pmapVectors):
"""Get the writers needed by dorothea"""
return self.create_kr_event(pmapVectors)

def write_parameters(self, h5out):
pass
2 changes: 1 addition & 1 deletion invisible_cities/cities/dorothea_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ def test_dorothea_KrMC(config_tmpdir, KrMC_pmaps):
dorothea.run()
cnt = dorothea.end()
nevt_in = cnt.n_events_tot
nevt_out = cnt.nevt_out
nevt_out = cnt.n_events_selected
if nrequired > 0:
assert nrequired == nevt_in
assert nevt_out <= nevt_in
Expand Down
3 changes: 3 additions & 0 deletions invisible_cities/cities/isidora.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,9 @@ def get_writers(self, h5out):

return writers

def write_parameters(self, h5out):
pass

def display_IO_info(self):
"""display info"""
super().display_IO_info()
Expand Down
84 changes: 9 additions & 75 deletions invisible_cities/cities/penthesilea.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,91 +3,25 @@
description: Read PMAPS and produces hits and beyond
credits: see ic_authors_and_legal.rst in /doc
last revised: JJGC, July-2017
last revised: JJGC, September-2017
"""

import numpy as np
import tables as tb

from .. core.configure import configure
from .. core.system_of_units_c import units
from .. types.ic_types import xy
from .. io.hits_io import hits_writer
from .. cities.base_cities import City
from .. cities.base_cities import HitCity
from .. cities.base_cities import EventLoop
from .. evm.event_model import Cluster
from .. evm.ic_containers import PmapVectors
from .. reco import tbl_functions as tbl

from .. filters.s1s2_filter import s1s2_filter
from .. filters.s1s2_filter import s2si_filter
from .. filters.s1s2_filter import S12Selector

class Penthesilea(HitCity):
"""Read PMAPS and produces hits and beyond"""
"""Read PMAPS and produces a HDST"""

def __init__(self, **kwds):
"""actions:
1. inits base city
2. inits counters
3. inits s1s2 selector
"""
super().__init__(**kwds)
conf = self.conf

self.cnt.init(n_events_tot = 0,
nevt_out = 0)
self.drift_v = conf.drift_v
self._s1s2_selector = S12Selector(**kwds)


def event_loop(self, pmapVectors):
"""actions:
1. loops over all PMAPS
2. filter pmaps
3. write hit_event
"""

write_hits = self.writers
event_numbers= pmapVectors.events
timestamps = pmapVectors.timestamps
s1_dict = pmapVectors.s1
s2_dict = pmapVectors.s2
s2si_dict = pmapVectors.s2si

for evt_number, evt_time in zip(event_numbers, timestamps):
self.conditional_print(self.cnt.n_events_tot, self.cnt.nevt_out)

# Count events in and break if necessary before filtering
what_next = self.event_range_step()
if what_next is EventLoop.skip_this_event: continue
if what_next is EventLoop.terminate_loop : break
self.cnt.n_events_tot += 1

# get pmaps
s1, s2, s2si = self. get_pmaps_from_dicts(s1_dict,
s2_dict,
s2si_dict,
evt_number)
# filtering
# loop event away if any signal (s1, s2 or s2si) not present
if s1 == None or s2 == None or s2si == None:
continue
# filters in s12 and s2si
f1 = s1s2_filter(self._s1s2_selector, s1, s2, s2si)
f2 = s2si_filter(s2si)
if not f1 or not f2:
continue
# event passed selection: increment counter and write
self.cnt.nevt_out += 1
pmapVectors = PmapVectors(s1=s1, s2=s2, s2si=s2si,
events = evt_number,
timestamps = evt_time)
evt = self.create_hits_event(pmapVectors)
write_hits(evt)

def get_writers(self, h5out):
"""Get the writers needed by dorothea"""
return hits_writer(h5out)

def create_dst_event(self, pmapVectors):
"""Get the writers needed by dorothea"""
return self.create_hits_event(pmapVectors)

def write_parameters(self, h5out):
pass
2 changes: 2 additions & 0 deletions invisible_cities/core/configure_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -300,6 +300,8 @@ def __init__(self, **kwds):
self.cnt.n_events_tot = 10

def file_loop(self): pass
def get_writers(self, h5out): pass
def write_parameters(self, h5out): pass


def test_config_drive_fails_without_config_file():
Expand Down

0 comments on commit eb903c7

Please sign in to comment.