예제 #1
0
   def urand_get_dur_list(self, nevents, tot_time):
      """return a list of durations, distributed uniformly in [0,max_dur]
         (but still on t_gran)

         - mean time is tot/n, max is 2*tot/n

         - get int(n/2) random times
         - fill with max-val (so pairs average at mean)
         - if n is odd, append one mean duration
         - shuffle
      """

      if nevents <= 0: return []
      if nevents == 1: return [tot_time]

      max_dur = tot_time * 2.0 / nevents

      # maximum num t_gran possibile (equates to 0..max_dur in time)
      # (+0.01 is to avoid a close trunction miss)
      nmax = int(max_dur / self.t_gran + 0.01)

      durlist = []
      for ind in range(nevents//2):
         ngran = self.rand_uniform_int(nmax+1)
         # add time and balancing time
         durlist.append(ngran * self.t_gran)
         durlist.append((nmax - ngran) * self.t_gran)

      if nevents % 2:
         durlist.append(max_dur/2.0)

      UTIL.shuffle(durlist)

      return durlist
예제 #2
0
   def decay_fixed_get_dur_list(self, nevents, tot_time, max_dur):
      """return a list of durations, distributed as e^-x on [0, max_dur]
         with mean tot_time/nevents (durations are still on t_gran)

         - mean time is tot/n, max should be positive

         - get n times via decay_pdf_get_ranged_times()
         - shuffle
      """

      import afnipython.lib_decay_timing as LDT

      if nevents <= 0: return []
      if nevents == 1: return [tot_time]
      if tot_time <= 0.0: return [0.0]*nevents

      if max_dur <= 0:
         print('** decay_fixed_GDL: illegal max_dur %g' % max_dur)
         return []

      mean = float(tot_time)/nevents

      durlist = LDT.decay_pdf_get_ranged_times(0, max_dur, mean, nevents,
                                      t_grid=self.t_gran, verb=self.verb)

      UTIL.shuffle(durlist)

      return durlist
예제 #3
0
   def ugrid_get_dur_list(self, nevents, tot_time):
      """return a list of durations, distributed evenly along [0,max_dur],
         but truncated to the t_gran grid

         EXPECTS: minimum event time == 0, i.e. old min was subtracted out
         
         - like urand, but create a list of evenly divided times, 
           without any randomness

         - mean time is tot/n, max is 2*tot/n

         - make int(n/2) lower grid times
            - compute exact time, then convert to t_gran indices (val)
         - fill with max-val (so pairs average at mean)
         - if n is odd, append one mean duration
         - shuffle
      """

      if nevents <= 0: return []
      if nevents == 1: return [tot_time]

      max_dur = tot_time * 2.0 / nevents
      tspace = max_dur / (nevents - 1.0)

      # maximum num t_gran possibile (equates to 0..max_dur in time)
      # (+0.01 is to avoid a close trunction miss)
      nmax = int(max_dur / self.t_gran + 0.01)

      durlist = []
      for ind in range(nevents//2):
         actual_time = ind * tspace
         grid_time = self.t_gran * int(actual_time/self.t_gran)
         # add time and balancing time
         durlist.append(grid_time)
         durlist.append(max_dur - grid_time)

      # if odd number, include a mean dur
      if nevents % 2:
         durlist.append(max_dur/2.0)

      UTIL.shuffle(durlist)

      return durlist
예제 #4
0
   def decay_apply_max_limit(self, dlist, nmax):
      """none of the (integer) entries in dlist should exceed nmax

         instead of:
            - truncating all big times to max (too many max's)
            - adding each extra time unit to a random event
         now:
            - give all big times new times on a uniform grid
            - distribute time in random blocks one event at a time:
              while time to distribute exists
                 choose a non-max event
                 add random amount of time (subject to max and total)
            - re-randomize list (so we can separate maxed out events)
      """

      nevents = len(dlist)
      intotal = sum(dlist) * self.t_gran

      if self.verb > 3:
         print('-- decay: dist %d rest events, time=%g, ave time=%g' \
               % (nevents, intotal, intotal/nevents))

      # give big times new ones in the proper range, and tally lost time
      textra = 0
      nfixed = 0
      for dind, dur in enumerate(dlist):
         if dur > nmax:
            dnew = self.rand_uniform_int(nmax+1)
            textra += (dur-dnew)
            nfixed += 1
            dlist[dind] = dnew

      # now remove any that are maxed out
      addlist = [dur for dur in dlist if dur < nmax]
      nadd = len(addlist)
      nmaxed = nevents - nadd

      if self.verb > 4:
         ttotal = textra * self.t_gran
         print('-- decay: dist %d rest atoms (time=%g)' % (textra, ttotal))
         print('   nadd=%d, nmaxed=%d, nfixed=%d' % (nadd, nmaxed, nfixed))
         ttotal = sum(dlist) * self.t_gran
         print('   fix %g/%d = %g' % (ttotal,len(dlist),ttotal/len(dlist)))

      # and add remaining time until we are done until we are done
      while textra > 0:
         # should not occur:
         if nadd == 0:
            print('** rcr screw-up: nadd = 0')
            sys.exit(1)

         # get random index to add to
         aind = self.rand_uniform_int(nadd)

         # set max to add
         space = nmax - addlist[aind]

         # get random space in {1,...,space}
         # try linearly decreasing prob dist func
         rval = self.rand_uniform_int(space*space)
         ntoadd = rval//space
         if (rval % space) < ntoadd: ntoadd = rval % space
         ntoadd += 1

         if ntoadd > textra: ntoadd = textra
         addlist[aind] += ntoadd
         textra -= ntoadd

         # if maxed, pop...
         if addlist[aind] == nmax:
            nmaxed += 1
            addlist.pop(aind)
            nadd -= 1

      # finally, re-randomize list
      addlist.extend([nmax] * nmaxed)
      dlist = addlist
      UTIL.shuffle(dlist)
            
      outtotal = sum(dlist) * self.t_gran

      if self.verb > 3:
         print('-- final, ave %g/%d = %g' \
               % (outtotal, len(dlist), outtotal/len(dlist)))

      if intotal != outtotal:
         print('** decay - apply max: intotal %g != outtotal %g' \
               % (intotal, outtotal))

      return dlist
예제 #5
0
   def decay_get_dur_list(self, nevents, tot_time, max_dur, maxtype=0):
      """return a list of durations of length nevents, such that tot_time is
         distributed with PDF decay (okay, the discrete version, which is less)

         maxtype 0 means default delay function
      """

      durlist = [0] * nevents

      # see how much rest there is to distribute
      nrest = int(tot_time / self.t_gran)

      # if no rest, just return the 0-filled list
      if nrest < 1:
         return durlist

      # start by doing a simple random distribution at t_gran granularity
      # (partition time with nevents-1 dividers)
      elist = [1] * (nevents - 1)
      rlist = [0] * nrest

      elist.extend(rlist)

      UTIL.shuffle(elist)
      # add a trailer to count the final duration (since only n-1 dividers)
      elist.append(1)

      # now get counts
      posn = -1
      prev = posn
      for eind in range(nevents):
         # look for the next 1
         try: posn = elist.index(1, prev+1)
         except:
            print('** DGDL index failure, n = %d, elist = %s' % (nevents, elist))
            return durlist

         # rest count is number of zeros between prev and posn
         durlist[eind] = posn-prev-1
         prev = posn

      # if no maximum to deal with, we are done (scale by t_gran)
      if max_dur < 0:
         for dind in range(nevents):
            durlist[dind] *= self.t_gran
         return durlist

      # --------------------------------------------------
      # have a max duration, so redistribute the wealth

      nmax = int(max_dur / self.t_gran)

      # limit to maximum; have multiple methods to choose from
      if maxtype == 0:
         durlist = self.decay_apply_max_limit(durlist, nmax)
      elif maxtype == 1:
         durlist = self.decay_apply_max_limit_old(durlist, nmax)
      else:
         print('** decay limit, illegal maxtype %d' % maxtype)
         durlist = self.decay_apply_max_limit(durlist, nmax)

      # and finally, scale by t_gran
      for dind in range(len(durlist)):
         durlist[dind] *= self.t_gran

      return durlist