Ejemplo n.º 1
0
    def __init__(self,
                 t_window,
                 beta_multiplier,
                 max_pos_tests_per_week_per_100k,
                 intervention_times=None,
                 init_active=False):
        """
        Additional parameters:
        ----------------------
        max_pos_test_per_week : int
            If the number of positive tests per week exceeds this number the measure becomes active
        intervention_times : list of floats
            List of points in time at which interventions can be changed. If 'None' interventions can be changed at any time
        init_active : bool
            If true measure is active in the first week of the simulation when there are no test counts yet
        """

        super().__init__(t_window, beta_multiplier)
        self.max_pos_tests_per_week_per_100k = max_pos_tests_per_week_per_100k
        self.intervention_times = intervention_times
        self.intervention_history = InterLap()
        if init_active:
            self.intervention_history.update([
                (t_window.left, t_window.left + 7 * 24 - EPS, True)
            ])
def build_interval_list(features):
    inter = InterLap()
    feature_coords = [[
        feature.start - 1, feature.end - 1,
        [feature.attributes["copy_id"][0], feature]
    ] for feature in features]
    if len(feature_coords) > 0:
        inter.update(feature_coords)
    return inter
Ejemplo n.º 3
0
def getAED(query, reference):
    '''
    function to calcuate annotation edit distance between two mRNA transcript coordinates
    AED = 1 - (SN + SP / 2)
    SN = fraction of ref predicted
    SP = fraction prediction overlapping the ref
    '''
    def _length(listTup):
        len = 0
        for i in listTup:
            l = abs(i[0] - i[1])
            len += l
        return len

    #check if identical
    if query == reference:
        return '0.000'
    #make sure sorted
    rLen = _length(reference)
    refInterlap = InterLap(reference)
    RefPred = 0
    QueryOverlap = 0
    qLen = 0
    for exon in query:
        qLen += abs(exon[0] - exon[1])
        if exon in refInterlap:  #exon overlaps at least partially with reference
            hit = list(refInterlap.find(exon))
            for h in hit:
                diff = np.subtract(
                    exon, h)  #will return array of exon minus hit at each pos
                if diff[0] <= 0 and diff[
                        1] >= 0:  #then query exon covers ref exon
                    cov = abs(h[0] - h[1])
                    QueryOverlap += cov
                elif diff[0] <= 0 and diff[
                        1] < 0:  # means query partial covers ref
                    cov = abs(h[0] - exon[1])
                    QueryOverlap += cov
                elif diff[0] > 0 and diff[
                        1] >= 0:  #means query partial covers ref
                    cov = abs(exon[0] - h[1])
                    QueryOverlap += cov
                elif diff[0] > 0 and diff[1] < 1:
                    cov = abs(exon[0] - exon[1])
                    QueryOverlap += cov
    #calculate AED
    if qLen > 0 and rLen > 0:
        SP = QueryOverlap / float(qLen)
        SN = QueryOverlap / float(rLen)
        AED = 1 - ((SN + SP) / 2)
    else:
        AED = 0.000
    return '{:.3f}'.format(AED)
Ejemplo n.º 4
0
    def __init__(self, t_window, p_stay_home, max_pos_tests_per_week_per_100k, intervention_times=None, init_active=False):
        """
        Additional parameters:
        ----------------------
        max_pos_test_per_week : int
            If the number of positive tests per week exceeds this number the measure becomes active
        intervention_times : list of floats
            List of points in time at which measures can become active. If 'None' measures can be changed at any time
        """

        super().__init__(t_window, p_stay_home)
        self.max_pos_tests_per_week_per_100k = max_pos_tests_per_week_per_100k
        self.intervention_times = intervention_times
        self.intervention_history = InterLap()
        if init_active:
            self.intervention_history.update([(t_window.left, t_window.left + 7 * 24 - EPS, True)])
Ejemplo n.º 5
0
    def find(self, feature: Feature, fraction: Optional[float] = None) -> List[Feature]:
        def filter4Fraction(overlap_feature):
            if not fraction:
                return True

            overlap_in_bp = float(overlap_feature.get_overlap_in_bp_with(feature))

            if len(feature) == 0:
                overlap_fraction_relative_to_feature = 0.0
            else:
                overlap_fraction_relative_to_feature = overlap_in_bp / len(feature)

            if len(overlap_feature) == 0:
                overlap_fraction_relative_to_overlap_feature = 0.0
            else:
                overlap_fraction_relative_to_overlap_feature = overlap_in_bp / len(overlap_feature)

            return max(overlap_fraction_relative_to_feature,
                       overlap_fraction_relative_to_overlap_feature) >= fraction

        def toFeature(interval):
            return Feature(feature.chromosome,
                       interval[0], interval[1],
                       interval[2][FeatureSeq.NAME_ATTRIBUTE],
                       interval[2][FeatureSeq.SCORE_ATTRIBUTE])

        return list(filter(filter4Fraction,
                      map(toFeature,
                          self.chromosome2tree.get(feature.chromosome, InterLap()).find(feature.interval))))
Ejemplo n.º 6
0
    def _find_contacts(self, mob_traces):
        """Find contacts in a given list `mob_traces` of `Visit`s"""
        # Group mobility traces by site
        mob_traces_at_site = defaultdict(list)
        for v in mob_traces:
            mob_traces_at_site[v.site].append(v)

        # dict of dict of list of contacts:
        # i.e. contacts[i][j][k] = "k-th contact from i to j"
        contacts = {i: defaultdict(InterLap) for i in range(self.num_people)}

        # For each site s
        for s in range(self.num_sites):
            if self.verbose:
                print('Checking site ' + str(s + 1) + '/' +
                      str(self.num_sites),
                      end='\r')
            if len(mob_traces_at_site[s]) == 0:
                continue

            # Init the interval overlap matcher
            inter = InterLap()
            inter.update(mob_traces_at_site[s])
            # Match contacts
            for v in mob_traces_at_site[s]:
                v_time = (v.t_from, v.t_to)
                for vo in list(inter.find(other=v_time)):
                    # Ignore contacts with same individual
                    if v.indiv == vo.indiv:
                        continue
                    # Compute contact time
                    c_t_from = max(v.t_from, vo.t_from)
                    c_t_to = min(v.t_to, vo.t_to_shifted)
                    if c_t_to > c_t_from:
                        # Set contact tuple
                        c = Contact(t_from=c_t_from,
                                    t_to=c_t_to,
                                    indiv_i=v.indiv,
                                    indiv_j=vo.indiv,
                                    id_tup=(v.id, vo.id),
                                    site=s,
                                    duration=c_t_to - c_t_from)
                        # Add it to interlap
                        contacts[v.indiv][vo.indiv].update([c])

        return contacts
Ejemplo n.º 7
0
    def _group_mob_traces_by_indiv(self, mob_traces):
        """Group `mob_traces` by individual for faster queries.
        Returns a dict of dict of Interlap of the form:

            mob_traces_dict[i] = "Interlap of visits of indiv i"
        """
        mob_traces_dict = {i: InterLap() for i in range(self.num_people)}
        for v in mob_traces:
            mob_traces_dict[v.indiv].update([v])
        return mob_traces_dict
Ejemplo n.º 8
0
    def _group_mob_traces_by_site(self, mob_traces):
        """Group `mob_traces` by site for faster queries.
        Returns a dict of dict of Interlap of the form:

            mob_traces_dict[k] = "Interlap of visits at site k"
        """
        mob_traces_dict = {k: InterLap() for k in range(self.num_sites)}
        for v in mob_traces:
            mob_traces_dict[v.site].update([v])
        return mob_traces_dict
Ejemplo n.º 9
0
def _extract(information, genome, name):
    """Creates an intervalTree based on the information of the gtf line"""

    seqname = information["seqname"]
    start, end = int(information["start"]), int(information["end"])
    genome.setdefault(seqname, InterLap()).add((start - 1, end, information))

    gene_name = information["gene_name"]
    name.setdefault(gene_name[0], dict()).setdefault(gene_name,
                                                     []).append(information)
Ejemplo n.º 10
0
    def init_run(self, n_people, n_visits):
        """Init the measure for this run by sampling the outcome of each visit
        for each individual

        Parameters
        ----------
        n_people : int
            Number of people in the population
        n_visits : int
            Maximum number of visits of an individual
        """
        # Sample the outcome of the measure for each visit of each individual
        self.bernoulli_stay_home = np.random.binomial(
            1, self.p_stay_home, size=(n_people, n_visits))
        self.intervals_stay_home = [InterLap() for _ in range(n_people)]
        self._is_init = True
Ejemplo n.º 11
0
    def simulate(self, max_time, seed=None):
        """
        Simulate contacts between individuals in time window [0, max_time].

        Parameters
        ----------
        max_time : float
            Maximum time to simulate
        seed : int
            Random seed for mobility simulation

        Returns
        -------
        contacts : list of list of tuples
            A list of namedtuples containing the list of all contacts as
            namedtuples ('time_start', 'indiv_j', 'duration'), where:
            - `time_start` is the time the contact started
            - 'indiv_j' is the id of the individual the contact was with
            - 'duration' is the duration of the contact
        """
        self.max_time = max_time

        # Simulate mobility of each individuals to each sites
        if self.verbose:
            print(f'Simulate mobility for {max_time:.2f} time units... ',
                  end='',
                  flush=True)

        # simulate mobility traces
        all_mob_traces = self._simulate_mobility(max_time, seed)

        self.mob_traces_by_indiv = self._group_mob_traces_by_indiv(
            all_mob_traces)
        self.mob_traces_by_site = self._group_mob_traces_by_site(
            all_mob_traces)
        self.mob_traces = InterLap(ranges=all_mob_traces)

        # Initialize empty contact array
        self.contacts = {
            i: defaultdict(InterLap)
            for i in range(self.num_people)
        }
Ejemplo n.º 12
0
def read_exons(gtf, chrom, cutoff, coverage_array, exclude):
    genes = defaultdict(IntervalSet)
    splitters = defaultdict(IntervalSet)

    interlaps = []
    split_iv = InterLap()
    # preempt any bugs by checking that we are getting a particular chrom
    assert gtf[0] == "|", (
        "expecting a tabix query so we can handle chroms correctly")
    #f1 = open("selfchaincut.txt","a")
    #f2 = open("segdupscut.txt","a")
    #f3 = open("coveragecut.txt","a")
    for bed in exclude:
        # expecting a tabix query so we can handle chroms correctly
        a = "|tabix {bed} {chrom}".format(chrom=chrom, bed=bed)

        # any file that gets sent in will be used to split regions (just like
        # low-coverage). For example, we split on self-chains as well.
        #TODO: comment this block if you don't want any filtering by self-chains or segdups
        for toks in (
                x.strip().split("\t") for x in ts.nopen(a)
        ):  # adds self chains and segdups to splitters list, so that exons can be split, and they are removed from CCRs
            s, e = int(toks[1]), int(toks[2])
            split_iv.add((s, e))
            #if len(toks) > 3:
            #    f1.write("\t".join(toks)+"\n") # self chain
            #else:
            #    f2.write("\t".join(toks)+"\n") # segdups

    for toks in (x.rstrip('\r\n').split("\t") for x in ts.nopen(gtf)
                 if x[0] != "#"):
        if toks[2] not in ("CDS",
                           "stop_codon") or toks[1] not in ("protein_coding"):
            continue
        #if toks[0] != "1": break
        start, end = map(int, toks[3:5])
        gene = toks[8].split('gene_name "')[1].split('"', 1)[0]
        assert start <= end, toks
        key = toks[0], gene

        #cutoff = 0.3

        # find sections of exon under certain coverage.
        #TODO: comment this if we don't want coverage cutoff filtering
        if coverage_array[start - 1:end].min(
        ) < cutoff:  # doesn't bother to run these operations if there is not one bp below the cutoff
            #splitters[key].add([(start - 1, end)]) #this takes out the whole exon for one section of poor coverage
            a = coverage_array[start - 1:end]
            #print str(start-1),end,a
            is_under, locs = False, []  # generates "locs" for each exon"
            if a[0] < cutoff:
                locs.append([start - 1])
                is_under = True  # so you can initialize is_under
            for pos, v in enumerate(
                    a[1:], start=start
            ):  #enumerates positions in the coverage array starting at the beginning of the exon
                if v < cutoff:
                    if not is_under:
                        is_under = True
                        locs.append(
                            [pos - 1]
                        )  #start, coverage is in bed format, so pos-1 is necessary, since splitters are open left and right side
                else:
                    if is_under:
                        is_under = False
                        locs[-1].append(pos)  #end
            if is_under:
                locs[-1].append(
                    end
                )  # in this case would end splitter at the end of the exon
            splitters[key].add(map(tuple, locs))
            #for i in locs:
            #    f3.write(chrom+"\t"+"\t".join(map(str,i))+"\n")

        for s, e in split_iv.find((start - 1, end)):
            splitters[key].add([(s, e)])

        genes[key].add(
            [(start - 1, end)]
        )  # converts GTF exon coordinates to BED format (subtracts 1 from exon start)
    # sort by start so we can do binary search.
    genes = dict((k, sorted(v._vals)) for k, v in genes.iteritems())
    #ends = dict((k, sorted(v)) for k, v in ends.iteritems())
    splits, starts, ends = {}, {}, {}
    splitters = dict(splitters)
    for chrom_gene, sends in genes.iteritems():
        starts[chrom_gene] = [s[0] for s in sends]
        ends[chrom_gene] = [s[1] for s in sends]
        if chrom_gene in splitters:
            splits[chrom_gene] = splitters[chrom_gene]._vals

    return starts, ends, splits
Ejemplo n.º 13
0
        keep = False

    # from interval import interval
    from interlap import InterLap
    from interlap import Interval  # This class can auto merge overlapped regions.
    # interlap really significantly increased the search speed.

    irange = Interval()
    with open(args['-r'], 'r') as inf:
        for line in inf:
            line = line.strip()
            if line:
                ss = line.split()
                irange.add([(float(ss[0]), float(ss[1]))])

    inter = InterLap()
    inter.update(irange._as_tuples(irange))
    #-------------------------------------------------
    for line in sys.stdin:
        line = line.strip()
        if line:
            ss = line.split()
            try:
                v = int(ss[colValue])
                if keep:
                    if inter.__contains__((v, v)):
                        sys.stdout.write('%s\n' % (line))
                else:
                    if not (inter.__contains__((v, v))):
                        sys.stdout.write('%s\n' % (line))
Ejemplo n.º 14
0
    def find_contacts_of_indiv(self,
                               indiv,
                               tmin,
                               tmax,
                               tracing=False,
                               p_reveal_visit=1.0):
        """
        Finds all delta-contacts of person 'indiv' with any other individual after time 'tmin'
        and returns them as InterLap object.
        In the simulator, this function is called for `indiv` as infector.
        """

        if tracing is True and self.beacon_config is None:
            # If function is used for contact tracing and there are no beacons, can only trace direct contacts
            extended_time_window = 0
        else:
            # If used for infection simulation or used for tracing with beacons, capture also indirect contacts
            extended_time_window = self.delta

        contacts = InterLap()

        # iterate over all visits of `indiv` intersecting with the interval [tmin, tmax]
        infector_traces = self.mob_traces_by_indiv[indiv].find(
            (tmin, tmax if (tmax is not None) else np.inf))

        for inf_visit in infector_traces:

            # coin flip of whether infector `indiv` reveals their visit
            if tracing is True and np.random.uniform(
                    low=0.0, high=1.0) > p_reveal_visit:
                continue

            # find all contacts of `indiv` by querying visits of
            # other individuals during visit time of `indiv` at the same site
            # (including delta-contacts; if beacon_cache=0, delta-contacts get filtered out below)
            inf_visit_time = (inf_visit.t_from, inf_visit.t_to_shifted)
            concurrent_site_traces = self.mob_traces_by_site[
                inf_visit.site].find(inf_visit_time)

            for visit in concurrent_site_traces:
                # ignore visits of `indiv` since it is not a contact
                if visit.indiv == inf_visit.indiv:
                    continue

                # ignore if begin of visit is after tmax
                # this can happen if inf_visit starts just before tmax but continues way beyond tmax
                if visit.t_from > tmax:
                    continue

                # Compute contact time
                c_t_from = max(visit.t_from, inf_visit.t_from)
                c_t_to = min(visit.t_to, inf_visit.t_to + extended_time_window)
                c_t_to_direct = min(visit.t_to, inf_visit.t_to)  # only direct

                if c_t_to > c_t_from and c_t_to > tmin:
                    c = Contact(t_from=c_t_from,
                                t_to=c_t_to,
                                indiv_i=visit.indiv,
                                indiv_j=inf_visit.indiv,
                                id_tup=(visit.id, inf_visit.id),
                                site=inf_visit.site,
                                duration=c_t_to - c_t_from,
                                t_to_direct=c_t_to_direct)
                    contacts.update([c])

        return contacts
Ejemplo n.º 15
0
            min_index = min(min_index, where)
        # print 'item %r, count %r, minind %r' % (item, count, min_index)
        return count, -min_index

    # pick the highest-count/earliest item
    return max(groups, key=_auxfun)[0]


print(files)
br = []
rr = []
bc = 0  #count bouke
rc = 0  #count raoul

for x in files:
    inter = InterLap()
    b = tgt.read_textgrid(mypath + x + "B.TextGrid").tiers[1]
    r = tgt.read_textgrid(mypath + x + "R.TextGrid").tiers[1]
    bc += len(b)
    rc += len(r)
    inter.add([convert_to_float(i) for i in r])
    tot_overlaps = set()
    for i in b:
        interval = convert_to_float(i)
        overlaps = list(inter.find(interval))

        #print(interval[2])

        if (len(overlaps) > 0):
            overlaps = [tuple(x) for x in overlaps]
            for o in overlaps:
Ejemplo n.º 16
0
class UpperBoundCasesBetaMultiplier(BetaMultiplierMeasure):

    def __init__(self, t_window, beta_multiplier, max_pos_tests_per_week_per_100k, intervention_times=None, init_active=False):
        """
        Additional parameters:
        ----------------------
        max_pos_test_per_week : int
            If the number of positive tests per week exceeds this number the measure becomes active
        intervention_times : list of floats
            List of points in time at which interventions can be changed. If 'None' interventions can be changed at any time
        init_active : bool
            If true measure is active in the first week of the simulation when there are no test counts yet
        """

        super().__init__(t_window, beta_multiplier)
        self.max_pos_tests_per_week_per_100k = max_pos_tests_per_week_per_100k
        self.intervention_times = intervention_times
        self.intervention_history = InterLap()
        if init_active:
            self.intervention_history.update([(t_window.left, t_window.left + 7 * 24 - EPS, True)])

    def init_run(self, n_people, n_visits):
        self.scaled_test_threshold = self.max_pos_tests_per_week_per_100k / 100000 * n_people
        self._is_init = True

    @enforce_init_run
    def _is_measure_active(self, t, t_pos_tests):
        # If measures can only become active at 'intervention_times'
        if self.intervention_times is not None:
            # Find largest 'time' in intervention_times s.t. t > time
            intervention_times = np.asarray(self.intervention_times)
            idx = np.where(t - intervention_times > 0, t - intervention_times, np.inf).argmin()
            t = intervention_times[idx]

        t_in_history = list(self.intervention_history.find((t, t)))
        if t_in_history:
            is_active = t_in_history[0][2]
        else:
            is_active = self._are_cases_above_threshold(t, t_pos_tests)
            if is_active:
                self.intervention_history.update([(t, t+7*24 - EPS, True)])
        return is_active

    @enforce_init_run
    def _are_cases_above_threshold(self, t, t_pos_tests):
        # Count positive tests in last 7 days from last intervention time
        tmin = t - 7 * 24
        num_pos_tests = np.sum(np.greater(t_pos_tests, tmin) * np.less(t_pos_tests, t))
        is_above_threshold = num_pos_tests > self.scaled_test_threshold
        return is_above_threshold

    @enforce_init_run
    def beta_factor(self, *, typ, t, t_pos_tests):
        """Returns the multiplicative factor for site type `typ` at time `t`. The
        factor is one if `t` is not in the active time window of the measure.
        """
        if not self._in_window(t):
            return 1.0

        is_measure_active = self._is_measure_active(t, t_pos_tests)
        return self.beta_multiplier[typ] if is_measure_active else 1.0
Ejemplo n.º 17
0
def findUTRs(cds, mrna, strand):
    '''
    take list of list of CDS coordiantes and compare to list of list of mRNA coordinates to
    determine if 5 prime or 3 prime UTR exist
    '''
    #supporting multiple transcripts, however, they are already matched up and sorted
    UTRs = []
    for i in range(0, len(cds)):
        Fiveprime = False
        Threeprime = False
        refInterlap = InterLap(mrna[i])
        if strand == '+':  #look at first CDS for 5 prime and last CDS for 3 prime
            if cds[i][
                    0] in refInterlap:  #means it overlaps with mrNA (which it obviously should)
                hit = list(refInterlap.find(cds[i][0]))[0]
                loc = mrna[i].index(
                    hit
                )  #if first exon, then compare, if not first then there is 5prime UTR
                if loc == 0:
                    diff = np.subtract(
                        cds[i][0],
                        hit)  #will return array of exon minus hit at each pos
                    if diff[0] > 0:
                        Fiveprime = True
                else:
                    Fiveprime = True
            #check for 3 prime UTR
            if cds[i][-1] in refInterlap:
                hit = list(refInterlap.find(cds[i][-1]))[0]
                loc = mrna[i].index(hit)
                if len(mrna[i]) == loc + 1:
                    diff = np.subtract(
                        cds[i][-1],
                        hit)  #will return array of exon minus hit at each pos
                    if diff[1] < 0:
                        Threeprime = True
                else:
                    Threeprime = True
        else:
            if cds[i][
                    0] in refInterlap:  #means it overlaps with mrNA (which it obviously should)
                hit = list(refInterlap.find(cds[i][0]))[0]
                loc = mrna[i].index(
                    hit
                )  #if first exon, then compare, if not first then there is 5prime UTR
                if loc == 0:
                    diff = np.subtract(
                        cds[i][0],
                        hit)  #will return array of exon minus hit at each pos
                    if diff[1] < 0:
                        Fiveprime = True
                else:
                    Fiveprime = True
            #check for 3 prime UTR
            if cds[i][-1] in refInterlap:
                hit = list(refInterlap.find(cds[i][-1]))[0]
                loc = mrna[i].index(hit)
                if len(mrna[i]) == loc + 1:
                    diff = np.subtract(
                        cds[i][-1],
                        hit)  #will return array of exon minus hit at each pos
                    if diff[0] > 0:
                        Threeprime = True
                else:
                    Threeprime = True
        UTRs.append((Fiveprime, Threeprime))
    return UTRs
Ejemplo n.º 18
0
 def init_run(self, n_people):
     """Init the measure for this run. Sampling of Bernoulli of respecting the measure done online."""
     self.intervals_isolated = [InterLap() for _ in range(n_people)]
     self._is_init = True
Ejemplo n.º 19
0
    itvMap = {}  #chr - >intervals.
    #irange = interval()
    with open(args['-r'], 'r') as inf:
        for line in inf:
            line = line.strip()
            if line:
                ss = line.split()
                if not (ss[0] in itvMap):
                    itvMap[ss[0]] = Interval()

                itvMap[ss[0]].add([(float(ss[1]), float(ss[2]))
                                   ])  # auto merge region.

    checkMap = {}
    for k, v in itvMap.items():
        inter = InterLap()
        inter.update(v._as_tuples(v))
        checkMap[k] = inter  # convert inverval to trees.
        # for i in inter:
        #     print(i)
#-------------------------------------------------
# print(checkMap)
    for line in sys.stdin:
        line = line.strip()
        if line:
            if title:
                sys.stdout.write('%s\n' % (line))
                title = False
                continue

            ss = line.split()
Ejemplo n.º 20
0
class UpperBoundCasesSocialDistancing(SocialDistancingForAllMeasure):

    def __init__(self, t_window, p_stay_home, max_pos_tests_per_week_per_100k, intervention_times=None, init_active=False):
        """
        Additional parameters:
        ----------------------
        max_pos_test_per_week : int
            If the number of positive tests per week exceeds this number the measure becomes active
        intervention_times : list of floats
            List of points in time at which measures can become active. If 'None' measures can be changed at any time
        """

        super().__init__(t_window, p_stay_home)
        self.max_pos_tests_per_week_per_100k = max_pos_tests_per_week_per_100k
        self.intervention_times = intervention_times
        self.intervention_history = InterLap()
        if init_active:
            self.intervention_history.update([(t_window.left, t_window.left + 7 * 24 - EPS, True)])

    def init_run(self, n_people, n_visits):
        super().init_run(n_people, n_visits)
        self.scaled_test_threshold = self.max_pos_tests_per_week_per_100k / 100000 * n_people

    def _is_measure_active(self, t, t_pos_tests):
        # If measures can only become active at 'intervention_times'
        if self.intervention_times is not None:
            # Find largest 'time' in intervention_times s.t. t > time
            intervention_times = np.asarray(self.intervention_times)
            idx = np.where(t - intervention_times > 0, t - intervention_times, np.inf).argmin()
            t = intervention_times[idx]

        t_in_history = list(self.intervention_history.find((t, t)))
        if t_in_history:
            is_active = t_in_history[0][2]
        else:
            is_active = self._are_cases_above_threshold(t, t_pos_tests)
            if is_active:
                self.intervention_history.update([(t, t + 7 * 24 - EPS, True)])
        return is_active

    def _are_cases_above_threshold(self, t, t_pos_tests):
        # Count positive tests in last 7 days from last intervention time
        tmin = t - 7 * 24
        num_pos_tests = np.sum(np.greater(t_pos_tests, tmin) * np.less(t_pos_tests, t))
        is_above_threshold = num_pos_tests > self.scaled_test_threshold
        return is_above_threshold

    @enforce_init_run
    def is_contained(self, *, j, j_visit_id, t, t_pos_tests):
        """Indicate if individual `j` respects measure for visit `j_visit_id`
        """
        if not self._in_window(t):
            return False

        is_home_now = self.bernoulli_stay_home[j, j_visit_id]
        return is_home_now and self._is_measure_active(t, t_pos_tests)

    @enforce_init_run
    def is_contained_prob(self, *, j, t, t_pos_tests):
        """Returns probability of containment for individual `j` at time `t`
        """
        if not self._in_window(t):
            return 0.0

        if self._is_measure_active(t, t_pos_tests):
            return self.p_stay_home
        return 0.0
Ejemplo n.º 21
0
    def _find_mob_trace_overlaps(self, sites, mob_traces_at_site,
                                 infector_mob_traces_at_site, tmin,
                                 for_all_individuals):

        # decide way of storing depending on way the function is used (all or individual)
        # FIXME: this could be done in a cleaner way by calling this function several times in `_find_contacts`
        if for_all_individuals:
            # dict of dict of list of contacts:
            # i.e. contacts[i][j][k] = "k-th contact from i to j"
            contacts = {
                i: defaultdict(InterLap)
                for i in range(self.num_people)
            }
        else:
            contacts = InterLap()

        if self.verbose and for_all_individuals:
            print()  # otherwise jupyter notebook looks ugly

        for s in sites:
            if self.verbose and for_all_individuals:
                print('Checking site ' + str(s + 1) + '/' + str(len(sites)),
                      end='\r')
            if len(mob_traces_at_site[s]) == 0:
                continue

            # Init the interval overlap matcher
            inter = InterLap()
            inter.update(mob_traces_at_site[s])

            # Match contacts
            # Iterate over each visit of the infector at site s
            for v_inf in infector_mob_traces_at_site[s]:

                # Skip if delta-contact ends before `tmin`
                if v_inf.t_to_shifted > tmin:

                    v_time = (v_inf.t_from, v_inf.t_to_shifted)

                    # Find any othe person that had overlap with this visit
                    for v in list(inter.find(other=v_time)):

                        # Ignore contacts with same individual
                        if v.indiv == v_inf.indiv:
                            continue

                        # Compute contact time
                        c_t_from = max(v.t_from, v_inf.t_from)
                        c_t_to = min(v.t_to, v_inf.t_to_shifted)
                        if c_t_to > c_t_from and c_t_to > tmin:

                            # Init contact tuple
                            # Note 1: Contact always considers delta overlap for `indiv_j`
                            # (i.e. for `indiv_j` being the infector)
                            # Note 2: Contact contains the delta-extended visit of `indiv_j`
                            # (i.e. there is a `Contact` even when `indiv_j` never overlapped physically with `indiv_i`)
                            # (i.e. need to adjust for that in dY_i integral)
                            c = Contact(t_from=c_t_from,
                                        t_to=c_t_to,
                                        indiv_i=v.indiv,
                                        indiv_j=v_inf.indiv,
                                        id_tup=(v.id, v_inf.id),
                                        site=s,
                                        duration=c_t_to - c_t_from)

                            # Add it to interlap
                            if for_all_individuals:
                                # Dictionary of all contacts
                                contacts[v.indiv][v_inf.indiv].update([c])
                            else:
                                # All contacts of (infector) 'indiv' only
                                contacts.update([c])
        return contacts
Ejemplo n.º 22
0
    def from_json(fp, compute_contacts=True):
        """
        Reach the from `fp` (.read()-supporting file-like object) that is
        expected to be JSON-formated from the `to_json` file.

        Parameters
        ----------
        fp : object
            The input .read()-supporting file-like object
        compute_contacts : bool (optional, default: True)
            Indicate if contacts should be computed from the mobility traces.
            If True, then any `contact` key in `fp` will be ignored.
            If False, `fp` must have a contact` key.

        Return
        ------
        sim : MobilitySimulator
            The loaded object
        """
        # Read file into json dict
        data = json.loads(fp.read())

        # Init object
        init_attrs = [
            'num_people', 'num_sites', 'delta', 'mob_mean', 'dur_mean',
            'verbose'
        ]
        obj = MobilitySimulator(**{attr: data[attr] for attr in init_attrs})

        # Set np.ndarray attributes
        for attr in ['home_loc', 'site_loc']:
            setattr(obj, attr, np.array(data[attr]))

        # Set list attributes
        for attr in ['visit_counts']:
            setattr(obj, attr, list(data[attr]))

        # Set `mob_traces` attribute into dict:defaultdict:InterLap
        setattr(obj, 'mob_traces',
                {i: defaultdict(InterLap)
                 for i in range(obj.num_people)})
        for indiv, traces_i in data['mob_traces'].items():
            indiv = int(indiv)  # JSON does not support int keys
            for site, visit_list in traces_i.items():
                site = int(site)  # JSON does not support int keys
                if len(visit_list) > 0:
                    inter = InterLap()
                    inter.update(list(map(lambda t: Visit(*t), visit_list)))
                    obj.mob_traces[indiv][site] = inter

        # Set `contacts` attribute into dict:defaultdict:InterLap
        if compute_contacts:  # Compute from `mob_traces`
            all_mob_traces = []
            for i, traces_i in obj.mob_traces.items():
                for j, inter in traces_i.items():
                    all_mob_traces.extend(inter._iset)
            # Compute contacts from mobility traces
            obj.contacts = obj._find_contacts(all_mob_traces)
        else:  # Load from file
            setattr(obj, 'contacts',
                    {i: defaultdict(InterLap)
                     for i in range(obj.num_people)})
            for indiv_i, contacts_i in data['contacts'].items():
                indiv_i = int(indiv_i)  # JSON does not support int keys
                for indiv_j, contact_list in contacts_i.items():
                    indiv_j = int(indiv_j)  # JSON does not support int keys
                    if len(contact_list) > 0:
                        inter = InterLap()
                        inter.update(
                            list(map(lambda t: Contact(*t), contact_list)))
                        obj.contacts[indiv_i][indiv_j] = inter

        return obj