Skip to content

Documentation for Box.py

Box

Note: this module is still under development and might change significantly.

ArrayGrid

ArrayGrid(min_rt, max_rt, rt_box_size, min_mz, max_mz, mz_box_size)

Bases: Grid

A dense, lossy implementation of the grid.

Source code in vimms/Box.py
348
349
350
351
352
353
354
355
356
def __init__(self, min_rt, max_rt, rt_box_size, min_mz, max_mz, mz_box_size):
    self.min_rt, self.max_rt = min_rt, max_rt
    self.min_mz, self.max_mz = min_mz, max_mz
    self.rt_box_size, self.mz_box_size = rt_box_size, mz_box_size
    self.box_area = float(Decimal(rt_box_size) * Decimal(mz_box_size))

    self.rtboxes = range(0, int((self.max_rt - self.min_rt) / rt_box_size) + 2)
    self.mzboxes = range(0, int((self.max_mz - self.min_mz) / mz_box_size) + 2)
    self.boxes = self.init_boxes(self.rtboxes, self.mzboxes)

BoxExact

Bases: BoxGeometry

splitting_intensity_non_overlap staticmethod

splitting_intensity_non_overlap(
    box, other_boxes, current_intensity, scoring_params
)

Will give nonsense results if other_boxes overlap each other.

Source code in vimms/Box.py
759
760
761
762
763
764
765
766
767
768
769
@staticmethod
def splitting_intensity_non_overlap(box, other_boxes, current_intensity, scoring_params):
    """Will give nonsense results if other_boxes overlap each other."""
    areas = [box.overlap_raw(b) for b in other_boxes]
    non_overlapped = max(0.0, 1.0 - sum(areas) / box.area())
    non_overlap = current_intensity**non_overlapped
    refragment = sum(
        max(0.0, current_intensity - b.intensity) ** (area / box.area())
        for b, area in zip(other_boxes, areas)
    )
    return non_overlap + scoring_params["theta1"] * refragment

BoxGeometry

Describes the interface for an abstract class which can do geometric operations on points, intervals and rectangles. Different subclasses use different data structures, and hence the choice of data structure matters for performance.

BoxLineSweeper

BoxLineSweeper()

Bases: BoxExact

Source code in vimms/Box.py
966
967
968
def __init__(self):
    self.lswp = LineSweeper()
    self.running_scores = dict()

non_overlap

non_overlap(box)

NB: This won't work if the boxes are capable of moving between time updates.

Source code in vimms/Box.py
 991
 992
 993
 994
 995
 996
 997
 998
 999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
def non_overlap(self, box):
    """NB: This won't work if the boxes are capable of moving between time updates."""
    sliced = box.copy()
    sliced.pt1.x = self.lswp.previous_loc

    other_boxes = (
        self.lswp.interval_overlaps_which_boxes(
            Interval(
                self.lswp.current_loc,
                self.lswp.current_loc,
                sliced.pt1.y,
                sliced.pt2.y,
            )
        )
        + self.lswp.was_active
    )  # TODO: If the manual intersection check is removed from this
    # non-overlap, then filter to intersecting boxes
    sliced_uncovered = sum(b.area() for b in BoxExact.non_overlap_boxes(sliced, other_boxes))

    running_uncovered, running_total = self.running_scores.get(sliced.id, (0, 0))
    running_uncovered += sliced_uncovered
    running_total += sliced.area()
    self.running_scores[sliced.id] = (running_uncovered, running_total)

    return running_uncovered / running_total

DictGrid

DictGrid(min_rt, max_rt, rt_box_size, min_mz, max_mz, mz_box_size)

Bases: Grid

A sparse, lossless implementation of the grid.

Source code in vimms/Box.py
348
349
350
351
352
353
354
355
356
def __init__(self, min_rt, max_rt, rt_box_size, min_mz, max_mz, mz_box_size):
    self.min_rt, self.max_rt = min_rt, max_rt
    self.min_mz, self.max_mz = min_mz, max_mz
    self.rt_box_size, self.mz_box_size = rt_box_size, mz_box_size
    self.box_area = float(Decimal(rt_box_size) * Decimal(mz_box_size))

    self.rtboxes = range(0, int((self.max_rt - self.min_rt) / rt_box_size) + 2)
    self.mzboxes = range(0, int((self.max_mz - self.min_mz) / mz_box_size) + 2)
    self.boxes = self.init_boxes(self.rtboxes, self.mzboxes)

GenericBox

GenericBox(
    x1,
    x2,
    y1,
    y2,
    parents=None,
    min_xwidth=0,
    min_ywidth=0,
    intensity=0,
    id=None,
    roi=None,
    round_digits=8,
)

Bases: Box

Makes no particular assumptions about bounding boxes.

Source code in vimms/Box.py
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
def __init__(
    self,
    x1,
    x2,
    y1,
    y2,
    parents=None,
    min_xwidth=0,
    min_ywidth=0,
    intensity=0,
    id=None,
    roi=None,
    round_digits=8,
):

    self.id = id
    self.roi = roi
    self.pt1 = Point(min(x1, x2), min(y1, y2), round_digits)
    self.pt2 = Point(max(x1, x2), max(y1, y2), round_digits)
    self.parents = [self] if parents is None else parents
    self.intensity = intensity
    self.round_digits = round_digits

    if self.pt2.x - self.pt1.x < min_xwidth:
        midpoint = self.pt1.x + (self.pt2.x - self.pt1.x) / 2
        self.pt1.x = midpoint - min_xwidth / 2
        self.pt2.x = midpoint + min_xwidth / 2

    if self.pt2.y - self.pt1.y < min_ywidth:
        midpoint = self.pt1.y + (self.pt2.y - self.pt1.y) / 2
        self.pt1.y = midpoint - min_ywidth / 2
        self.pt2.y = midpoint + min_ywidth / 2

non_overlap_split

non_overlap_split(other_box)

Finds 1 to 4 boxes describing the polygon of area of this box not overlapped by other_box. If one box is found, crops this box to dimensions of that box, and returns None. Otherwise, returns list of 2 to 4 boxes. Number of boxes found is equal to number of edges overlapping area does NOT share with this box.

Source code in vimms/Box.py
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
def non_overlap_split(self, other_box):
    """Finds 1 to 4 boxes describing the polygon of area of this box
    not overlapped by other_box. If one box is found, crops this box to
    dimensions of that box, and returns None. Otherwise, returns list of
    2 to 4 boxes. Number of boxes found is equal to number of edges
    overlapping area does NOT share with this box."""
    if not self.overlaps_with_box(other_box):
        return None
    x1, x2, y1, y2 = self.pt1.x, self.pt2.x, self.pt1.y, self.pt2.y
    split_boxes = []
    if other_box.pt1.x > self.pt1.x:
        x1 = other_box.pt1.x
        split_boxes.append(
            type(self)(self.pt1.x, x1, y1, y2, parents=self.parents, intensity=self.intensity)
        )
    if other_box.pt2.x < self.pt2.x:
        x2 = other_box.pt2.x
        split_boxes.append(
            type(self)(x2, self.pt2.x, y1, y2, parents=self.parents, intensity=self.intensity)
        )
    if other_box.pt1.y > self.pt1.y:
        y1 = other_box.pt1.y
        split_boxes.append(
            type(self)(x1, x2, self.pt1.y, y1, parents=self.parents, intensity=self.intensity)
        )
    if other_box.pt2.y < self.pt2.y:
        y2 = other_box.pt2.y
        split_boxes.append(
            type(self)(x1, x2, y2, self.pt2.y, parents=self.parents, intensity=self.intensity)
        )
    return split_boxes

Grid

Grid(min_rt, max_rt, rt_box_size, min_mz, max_mz, mz_box_size)

Partitions a 2D space into a number of rectangles of fixed size for faster lookup. If a query object and a saved object touch the same rectangle, then the saved object should be factored into the query.

Source code in vimms/Box.py
348
349
350
351
352
353
354
355
356
def __init__(self, min_rt, max_rt, rt_box_size, min_mz, max_mz, mz_box_size):
    self.min_rt, self.max_rt = min_rt, max_rt
    self.min_mz, self.max_mz = min_mz, max_mz
    self.rt_box_size, self.mz_box_size = rt_box_size, mz_box_size
    self.box_area = float(Decimal(rt_box_size) * Decimal(mz_box_size))

    self.rtboxes = range(0, int((self.max_rt - self.min_rt) / rt_box_size) + 2)
    self.mzboxes = range(0, int((self.max_mz - self.min_mz) / mz_box_size) + 2)
    self.boxes = self.init_boxes(self.rtboxes, self.mzboxes)

LocatorGrid

LocatorGrid(min_rt, max_rt, rt_box_size, min_mz, max_mz, mz_box_size)

Bases: Grid

A dense, lossless implementation of the grid.

Source code in vimms/Box.py
348
349
350
351
352
353
354
355
356
def __init__(self, min_rt, max_rt, rt_box_size, min_mz, max_mz, mz_box_size):
    self.min_rt, self.max_rt = min_rt, max_rt
    self.min_mz, self.max_mz = min_mz, max_mz
    self.rt_box_size, self.mz_box_size = rt_box_size, mz_box_size
    self.box_area = float(Decimal(rt_box_size) * Decimal(mz_box_size))

    self.rtboxes = range(0, int((self.max_rt - self.min_rt) / rt_box_size) + 2)
    self.mzboxes = range(0, int((self.max_mz - self.min_mz) / mz_box_size) + 2)
    self.boxes = self.init_boxes(self.rtboxes, self.mzboxes)