Exemplo n.º 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
Exemplo n.º 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
      """

        from afnipy import 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
Exemplo n.º 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
Exemplo n.º 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
Exemplo n.º 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