sim.py
Go to the documentation of this file.
1 #!/usr/bin/env python
2 '''
3 Work with sim data.
4 
5 fixme: this module is poorly named.
6 '''
7 
8 from wirecell import units
9 import numpy
10 import matplotlib.pyplot as plt
11 from mpl_toolkits.mplot3d import Axes3D
12 import matplotlib
13 matplotlib.rcParams['axes.formatter.useoffset'] = False
14 
15 def baseline_subtract(frame):
16  '''
17  Return a new frame array (chan x tick) were each channel row has
18  its baseline subtracted.
19  '''
20  # gotta transpose around to get the right shapes to trigger broadcasting.
21  return (frame.T - numpy.median(frame, axis=1)).T
22 
23 
25  if type(cb) != type(""):
26  return cb # assume already parsed.
27  return tuple(map(int, cb.split(',')))
28 
29 
30 def group_channel_indices(channels, boundaries=()):
31  '''
32  Given a list of channels, return a list of lists where each
33  sublist is a sequential set. If a sequence of boundaries are
34  given, then force a grouping on that channel even if there's not
35  jump.
36  '''
37 
38  print ("Channel boundaries: %s" % str(boundaries))
39 
40  channels = numpy.asarray(channels)
41  chan_list = channels.tolist()
42  binds = list()
43  for b in boundaries:
44  try:
45  i = chan_list.index(b)
46  except ValueError:
47  continue
48  binds.append(i)
49 
50  chd = channels[1:] - channels[:-1]
51  chjumps = [-1] + list(numpy.where(chd>1)[0]) + [channels.size-1]
52  ret = list()
53  for a,b in zip(chjumps[:-1], chjumps[1:]):
54  #print a,b,channels[a+1:b+1]
55  a += 1
56  b += 1
57 
58  gotsome = 0
59  for bind in binds:
60  if a < bind and bind < b:
61  ret.append((a,bind))
62  ret.append((bind,b))
63  gotsome += 1
64  if gotsome == 0:
65  ret.append((a,b))
66  return ret
67 
68 class Frame(object):
69  def __init__(self, fp, ident=0, tag=''):
70  def thing(n):
71  arr = fp['%s_%s_%d' % (n, tag, ident)]
72  if n == 'frame':
73  return arr.T
74  return arr
75 
76  for n in 'frame channels tickinfo'.split():
77  setattr(self, n, thing(n))
78 
80 
81  def plot_ticks(self, tick0=0, tickf=-1, raw=True, chinds = ()):
82  '''
83  Plot in terms of ticks. Here, the frame is assumed to be
84  dense and chinds are taken as channel ranges.
85  '''
86  frame = self.frame
87  print ("Frame shape: %s" % str(frame.shape))
88 
89  if not raw:
90  frame = baseline_subtract(frame)
91 
92 
93  if not chinds:
94  chinds = group_channel_indices(self.channels, self.channel_boundaries)
95 
96  tick = self.tickinfo[1]
97  if tickf < 0:
98  tickf += frame.shape[1]
99 
100  ngroups = len(chinds)
101  fig, axes = plt.subplots(nrows=ngroups, ncols=1, sharex = True)
102  if ngroups == 1:
103  axes = [axes] # always list
104 
105  for ax, chind in zip(axes, chinds):
106  ngroups -= 1
107  ch1 = self.channels[chind[0]]
108  ch2 = self.channels[chind[1]-1]
109 
110  extent = (tick0, tickf, ch2, ch1)
111  print ("exent: %s" % str(extent))
112 
113  im = ax.imshow(frame[chind[0]:chind[1],tick0:tickf],
114  aspect='auto', extent=extent, interpolation='none')
115  plt.colorbar(im, ax=ax)
116  if not ngroups:
117  ax.set_xlabel('ticks (%.2f us)' % (tick/units.us),)
118 
119  return fig,axes
120 
121  def plot(self, t0=None, tf=None, raw=True, chinds = ()):
122 
123  frame = self.frame
124  if not raw:
125  frame = baseline_subtract(frame)
126 
127  tstart, tick = self.tickinfo[:2]
128  nticks = frame.shape[1]
129  tend = tstart + nticks*tick
130 
131  if t0 is None or t0 < tstart or t0 > tend:
132  t0 = tstart
133 
134  if tf is None or tf < t0 or tf > tend:
135  tf = tend
136 
137  tick0 = int((t0-tstart)/tick)
138  tickf = int((tf-tstart)/tick)
139 
140  #print ("trange=[%.2f %.2f]ms ticks=[%d,%d]" % (t0/units.ms,tf/units.ms,tick0,tickf))
141 
142  if not chinds:
143  chinds = group_channel_indices(self.channels)
144  ngroups = len(chinds)
145  fig, axes = plt.subplots(nrows=ngroups, ncols=1, sharex = True)
146  if ngroups == 1:
147  axes = [axes] # always list
148 
149  for ax, chind in zip(axes, chinds):
150  ngroups -= 1
151  chind0 = chind[0]
152  chind1 = chind[1]
153 
154  ch1 = self.channels[chind0]
155  ch2 = self.channels[chind1-1]
156 
157  extent = (t0/units.ms, tf/units.ms, ch2, ch1)
158  print ("exent: %s, chind=(%d,%d)" % (str(extent), chind0, chind1) )
159 
160 
161  #print (chind,extent, chind, tick0, tickf, frame.shape)
162  im = ax.imshow(frame[chind0:chind1,tick0:tickf],
163  aspect='auto', extent=extent, interpolation='none')
164  plt.colorbar(im, ax=ax)
165  if not ngroups:
166  ax.set_xlabel('time [ms]')
167 
168  #plt.savefig(outfile)
169  return fig,axes
170 
171  #plt.imshow(fr[ch[0]:ch[1], ti[0]:ti[1]], extent=[ti[0], ti[1], ch[1], ch[0]], aspect='auto', interpolation='none'); plt.colorbar()
172 
173 
174 # f = numpy.load("test-boundaries.npz"); reload(sim);
175 # fo = sim.Frame(f)
176 # fo.plot()
177 # dd = f['depo_data_0']
178 # plt.scatter(dd[2]/units.m, dd[4]/units.m)
179 
180 class Depos(object):
181  def __init__(self, fp, ident=0):
182  # 7xN: t, q, x, y, z, dlong, dtran,
183  self.data = fp['depo_data_%d'%ident]
184  # 4xN: id, pdg, gen, child
185  self.info = fp['depo_info_%d'%ident]
186 
187  @property
188  def t(self):
189  return self.data[0]
190  @property
191  def q(self):
192  return self.data[1]
193  @property
194  def x(self):
195  return self.data[2]
196  @property
197  def y(self):
198  return self.data[3]
199  @property
200  def z(self):
201  return self.data[4]
202 
203  def plot(self):
204  fig = plt.figure()
205  ax10 = fig.add_subplot(223)
206  ax00 = fig.add_subplot(221)
207  ax11 = fig.add_subplot(224, sharey=ax10)
208  ax01 = fig.add_subplot(222, projection='3d')
209 
210 
211  ax00.hist(self.t/units.ms, 100)
212 
213  ax10.scatter(self.x/units.m, self.z/units.m)
214  ax11.scatter(self.y/units.m, self.z/units.m)
215  ax01.scatter(self.x/units.m, self.y/units.m, self.z/units.m)
216 
217  ax00.set_title('depo times [ms]');
218 
219  ax10.set_xlabel('x [m]');
220  ax10.set_ylabel('z [m]');
221  ax11.set_xlabel('y [m]');
222  ax11.set_ylabel('z [m]');
223 
224 
225  # fig, axes = plt.subplots(nrows=2, ncols=2)
226  # axes[0,0].scatter(self.x/units.m, self.y/units.m, sharex=axes[1,0])
227  # axes[1,0].scatter(self.x/units.m, self.z/units.m)
228  # axes[1,1].scatter(self.y/units.m, self.z/units.m, sharey=axes[1,0])
229  # axes[0,1].scatter(self.x/units.m, self.y/units.m, self.z/units.m)
230  return fig,(ax00,ax10,ax01,ax11)
231 
232 class NumpySaver(object):
233  def __init__(self, filename):
234  self.fname = filename
235  self.reload()
236 
237  def reload(self):
238  f = numpy.load(filename)
239 
def plot_ticks(self, tick0=0, tickf=-1, raw=True, chinds=())
Definition: sim.py:81
def q(self)
Definition: sim.py:191
def plot(self)
Definition: sim.py:203
def z(self)
Definition: sim.py:200
def plot(self, t0=None, tf=None, raw=True, chinds=())
Definition: sim.py:121
def parse_channel_boundaries(cb)
Definition: sim.py:24
def __init__(self, fp, ident=0, tag='')
Definition: sim.py:69
def baseline_subtract(frame)
Definition: sim.py:15
def x(self)
Definition: sim.py:194
def group_channel_indices(channels, boundaries=())
Definition: sim.py:30
def __init__(self, filename)
Definition: sim.py:233
def t(self)
Definition: sim.py:188
def __init__(self, fp, ident=0)
Definition: sim.py:181
auto zip(Iterables &&...iterables)
Range-for loop helper iterating across many collections at the same time.
Definition: zip.h:295
void split(std::string const &s, char c, OutIter dest)
Definition: split.h:35
def y(self)
Definition: sim.py:197
static QCString str