We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Randint is passed float bounds
I'm not sure what's causing this, but a user has this stack trace:

```
File "/opt/conda/lib/python3.6/runpy.py", line 193, in _run_module_as_main
    "__main__", mod_spec)
  File "/opt/conda/lib/python3.6/runpy.py", line 85, in _run_code
    exec(code, run_globals)
  File "/opt/src/rastervision/__main__.py", line 17, in <module>
    rv.main()
  File "/opt/conda/lib/python3.6/site-packages/click/core.py", line 722, in __call__
    return self.main(*args, **kwargs)
  File "/opt/conda/lib/python3.6/site-packages/click/core.py", line 697, in main
    rv = self.invoke(ctx)
  File "/opt/conda/lib/python3.6/site-packages/click/core.py", line 1066, in invoke
    return _process_result(sub_ctx.command.invoke(sub_ctx))
  File "/opt/conda/lib/python3.6/site-packages/click/core.py", line 895, in invoke
    return ctx.invoke(self.callback, **ctx.params)
  File "/opt/conda/lib/python3.6/site-packages/click/core.py", line 535, in invoke
    return callback(*args, **kwargs)
  File "/opt/src/rastervision/cli/main.py", line 294, in run_command
    rv.runner.CommandRunner.run(command_config_uri)
  File "/opt/src/rastervision/runner/command_runner.py", line 11, in run
    CommandRunner.run_from_proto(msg)
  File "/opt/src/rastervision/runner/command_runner.py", line 17, in run_from_proto
    command.run()
  File "/opt/src/rastervision/command/chip_command.py", line 29, in run
    task.make_chips(train_scenes, val_scenes, augmentors, tmp_dir)
  File "/opt/src/rastervision/task/task.py", line 127, in make_chips
    train_scenes, TRAIN, augment=True)
  File "/opt/src/rastervision/task/task.py", line 124, in _process_scenes
    return [_process_scene(scene, type_, augment) for scene in scenes]
  File "/opt/src/rastervision/task/task.py", line 124, in <listcomp>
    return [_process_scene(scene, type_, augment) for scene in scenes]
  File "/opt/src/rastervision/task/task.py", line 107, in _process_scene
    windows = self.get_train_windows(scene)
  File "/opt/src/rastervision/task/object_detection.py", line 107, in get_train_windows
    self.config.chip_options.label_buffer))
  File "/opt/src/rastervision/task/object_detection.py", line 58, in make_pos_windows
    return _make_chip_pos_windows(image_extent, label_store, chip_size)
  File "/opt/src/rastervision/task/object_detection.py", line 28, in _make_chip_pos_windows
    window = box.make_random_square_container(chip_size)
  File "/opt/src/rastervision/core/box.py", line 121, in make_random_square_container
    rand_x = random.randint(lb, ub)
  File "/opt/conda/lib/python3.6/random.py", line 221, in randint
    return self.randrange(a, b+1)
  File "/opt/conda/lib/python3.6/random.py", line 194, in randrange
    raise ValueError("non-integer stop for randrange()")
ValueError: non-integer stop for randrange()
/tmp/tmpxwof2zeo/tmp_wgvukcn/Makefile:6: recipe for target '1' failed
```

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `rastervision/core/box.py`
Content:
```
1 import math
2 import random
3 
4 import numpy as np
5 from shapely.geometry import box as ShapelyBox
6 
7 
8 class BoxSizeError(ValueError):
9     pass
10 
11 
12 class Box():
13     """A multi-purpose box (ie. rectangle)."""
14 
15     def __init__(self, ymin, xmin, ymax, xmax):
16         """Construct a bounding box.
17 
18         Unless otherwise stated, the convention is that these coordinates are
19         in pixel coordinates and represent boxes that lie within a
20         RasterSource.
21 
22         Args:
23             ymin: minimum y value (y is row)
24             xmin: minimum x value (x is column)
25             ymax: maximum y value
26             xmax: maximum x value
27 
28         """
29         self.ymin = ymin
30         self.xmin = xmin
31         self.ymax = ymax
32         self.xmax = xmax
33 
34     def __eq__(self, other):
35         """Return true if other has same coordinates."""
36         return self.tuple_format() == other.tuple_format()
37 
38     def __ne__(self, other):
39         """Return true if other has different coordinates."""
40         return self.tuple_format() != other.tuple_format()
41 
42     def get_height(self):
43         """Return height of Box."""
44         return self.ymax - self.ymin
45 
46     def get_width(self):
47         """Return width of Box."""
48         return self.xmax - self.xmin
49 
50     def get_area(self):
51         """Return area of Box."""
52         return self.get_height() * self.get_width()
53 
54     def rasterio_format(self):
55         """Return Box in Rasterio format."""
56         return ((self.ymin, self.ymax), (self.xmin, self.xmax))
57 
58     def tuple_format(self):
59         return (self.ymin, self.xmin, self.ymax, self.xmax)
60 
61     def shapely_format(self):
62         return (self.xmin, self.ymin, self.xmax, self.ymax)
63 
64     def to_int(self):
65         return Box(
66             int(self.ymin), int(self.xmin), int(self.ymax), int(self.xmax))
67 
68     def npbox_format(self):
69         """Return Box in npbox format used by TF Object Detection API.
70 
71         Returns:
72             Numpy array of form [ymin, xmin, ymax, xmax] with float type
73 
74         """
75         return np.array(
76             [self.ymin, self.xmin, self.ymax, self.xmax], dtype=np.float)
77 
78     @staticmethod
79     def to_npboxes(boxes):
80         """Return nx4 numpy array from list of Box."""
81         nb_boxes = len(boxes)
82         npboxes = np.empty((nb_boxes, 4))
83         for boxind, box in enumerate(boxes):
84             npboxes[boxind, :] = box.npbox_format()
85         return npboxes
86 
87     def __str__(self):  # pragma: no cover
88         return str(self.npbox_format())
89 
90     def __repr__(self):  # pragma: no cover
91         return str(self)
92 
93     def geojson_coordinates(self):
94         """Return Box as GeoJSON coordinates."""
95         # Compass directions:
96         nw = [self.xmin, self.ymin]
97         ne = [self.xmin, self.ymax]
98         se = [self.xmax, self.ymax]
99         sw = [self.xmax, self.ymin]
100         return [nw, ne, se, sw, nw]
101 
102     def make_random_square_container(self, size):
103         """Return a new square Box that contains this Box.
104 
105         Args:
106             size: the width and height of the new Box
107 
108         """
109         if size < self.get_width():
110             raise BoxSizeError('size of random container cannot be < width')
111 
112         if size < self.get_height():  # pragma: no cover
113             raise BoxSizeError('size of random container cannot be < height')
114 
115         lb = self.ymin - (size - self.get_height())
116         ub = self.ymin
117         rand_y = random.randint(lb, ub)
118 
119         lb = self.xmin - (size - self.get_width())
120         ub = self.xmin
121         rand_x = random.randint(lb, ub)
122 
123         return Box.make_square(rand_y, rand_x, size)
124 
125     def make_random_square(self, size):
126         """Return new randomly positioned square Box that lies inside this Box.
127 
128         Args:
129             size: the height and width of the new Box
130 
131         """
132         if size >= self.get_width():
133             raise BoxSizeError('size of random square cannot be >= width')
134 
135         if size >= self.get_height():  # pragma: no cover
136             raise BoxSizeError('size of random square cannot be >= height')
137 
138         lb = self.ymin
139         ub = self.ymax - size
140         rand_y = random.randint(lb, ub)
141 
142         lb = self.xmin
143         ub = self.xmax - size
144         rand_x = random.randint(lb, ub)
145 
146         return Box.make_square(rand_y, rand_x, size)
147 
148     def intersection(self, other):
149         """Return the intersection of this Box and the other.
150 
151         Args:
152             other: The box to intersect with this one.
153 
154         Returns:
155              The intersection of this box and the other one.
156 
157         """
158         xmin = max(self.xmin, other.xmin)
159         ymin = max(self.ymin, other.ymin)
160         xmax = min(self.xmax, other.xmax)
161         ymax = min(self.ymax, other.ymax)
162         return Box(xmin=xmin, ymin=ymin, xmax=xmax, ymax=ymax)
163 
164     @staticmethod
165     def from_npbox(npbox):
166         """Return new Box based on npbox format.
167 
168         Args:
169             npbox: Numpy array of form [ymin, xmin, ymax, xmax] with float type
170 
171         """
172         return Box(*npbox)
173 
174     @staticmethod
175     def from_shapely(shape):
176         bounds = shape.bounds
177         return Box(bounds[1], bounds[0], bounds[3], bounds[2])
178 
179     @staticmethod
180     def from_tuple(tup):
181         """Return new Box based on tuple format.
182 
183         Args:
184            tup: Tuple format box (ymin, xmin, ymax, xmax)
185         """
186         return Box(tup[0], tup[1], tup[2], tup[3])
187 
188     def to_shapely(self):
189         return ShapelyBox(*(self.shapely_format()))
190 
191     def reproject(self, transform_fn):
192         """Reprojects this box based on a transform function.
193 
194         Args:
195           transform_fn - A function that takes in a tuple (x, y)
196                          and reprojects that point to the target
197                          coordinate reference system.
198         """
199         (xmin, ymin) = transform_fn((self.xmin, self.ymin))
200         (xmax, ymax) = transform_fn((self.xmax, self.ymax))
201 
202         return Box(ymin, xmin, ymax, xmax)
203 
204     @staticmethod
205     def make_square(ymin, xmin, size):
206         """Return new square Box."""
207         return Box(ymin, xmin, ymin + size, xmin + size)
208 
209     def make_eroded(self, erosion_size):
210         """Return new Box whose sides are eroded by erosion_size."""
211         return Box(self.ymin + erosion_size, self.xmin + erosion_size,
212                    self.ymax - erosion_size, self.xmax - erosion_size)
213 
214     def make_buffer(self, buffer_size, max_extent):
215         """Return new Box whose sides are buffered by buffer_size.
216 
217         The resulting box is clipped so that the values of the corners are
218         always greater than zero and less than the height and width of
219         max_extent.
220 
221         """
222         buffer_size = max(0., buffer_size)
223         if buffer_size < 1.:
224             delta_width = int(round(buffer_size * self.get_width()))
225             delta_height = int(round(buffer_size * self.get_height()))
226         else:
227             delta_height = delta_width = int(round(buffer_size))
228 
229         return Box(
230             max(0, math.floor(self.ymin - delta_height)),
231             max(0, math.floor(self.xmin - delta_width)),
232             min(max_extent.get_height(),
233                 int(self.ymax) + delta_height),
234             min(max_extent.get_width(),
235                 int(self.xmax) + delta_width))
236 
237     def make_copy(self):
238         return Box(*(self.tuple_format()))
239 
240     def get_windows(self, chip_size, stride):
241         """Return list of grid of boxes within this box.
242 
243         Args:
244             chip_size: (int) the length of each square-shaped window in pixels
245             stride: (int) how much each window is offset from the last in pixels
246 
247         """
248         height = self.get_height()
249         width = self.get_width()
250 
251         result = []
252         for row_start in range(0, height, stride):
253             for col_start in range(0, width, stride):
254                 result.append(Box.make_square(row_start, col_start, chip_size))
255         return result
256 
257     def to_dict(self):
258         return {
259             'xmin': self.xmin,
260             'ymin': self.ymin,
261             'xmax': self.xmax,
262             'ymax': self.ymax
263         }
264 
265     @classmethod
266     def from_dict(cls, d):
267         return cls(d['ymin'], d['xmin'], d['ymax'], d['xmax'])
268 
269     @staticmethod
270     def filter_by_aoi(windows, aoi_polygons):
271         """Filters windows by a list of AOI polygons"""
272         result = []
273         for window in windows:
274             w = window.to_shapely()
275             for polygon in aoi_polygons:
276                 if w.within(polygon):
277                     result.append(window)
278                     break
279 
280         return result
281
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/rastervision/core/box.py b/rastervision/core/box.py
--- a/rastervision/core/box.py
+++ b/rastervision/core/box.py
@@ -114,11 +114,11 @@
 
         lb = self.ymin - (size - self.get_height())
         ub = self.ymin
-        rand_y = random.randint(lb, ub)
+        rand_y = random.randint(int(lb), int(ub))
 
         lb = self.xmin - (size - self.get_width())
         ub = self.xmin
-        rand_x = random.randint(lb, ub)
+        rand_x = random.randint(int(lb), int(ub))
 
         return Box.make_square(rand_y, rand_x, size)
 
@@ -137,11 +137,11 @@
 
         lb = self.ymin
         ub = self.ymax - size
-        rand_y = random.randint(lb, ub)
+        rand_y = random.randint(int(lb), int(ub))
 
         lb = self.xmin
         ub = self.xmax - size
-        rand_x = random.randint(lb, ub)
+        rand_x = random.randint(int(lb), int(ub))
 
         return Box.make_square(rand_y, rand_x, size)

{"golden_diff": "diff --git a/rastervision/core/box.py b/rastervision/core/box.py\n--- a/rastervision/core/box.py\n+++ b/rastervision/core/box.py\n@@ -114,11 +114,11 @@\n \n         lb = self.ymin - (size - self.get_height())\n         ub = self.ymin\n-        rand_y = random.randint(lb, ub)\n+        rand_y = random.randint(int(lb), int(ub))\n \n         lb = self.xmin - (size - self.get_width())\n         ub = self.xmin\n-        rand_x = random.randint(lb, ub)\n+        rand_x = random.randint(int(lb), int(ub))\n \n         return Box.make_square(rand_y, rand_x, size)\n \n@@ -137,11 +137,11 @@\n \n         lb = self.ymin\n         ub = self.ymax - size\n-        rand_y = random.randint(lb, ub)\n+        rand_y = random.randint(int(lb), int(ub))\n \n         lb = self.xmin\n         ub = self.xmax - size\n-        rand_x = random.randint(lb, ub)\n+        rand_x = random.randint(int(lb), int(ub))\n \n         return Box.make_square(rand_y, rand_x, size)\n", "issue": "Randint is passed float bounds\nI'm not sure what's causing this, but a user has this stack trace:\r\n\r\n```\r\nFile \"/opt/conda/lib/python3.6/runpy.py\", line 193, in _run_module_as_main\r\n    \"__main__\", mod_spec)\r\n  File \"/opt/conda/lib/python3.6/runpy.py\", line 85, in _run_code\r\n    exec(code, run_globals)\r\n  File \"/opt/src/rastervision/__main__.py\", line 17, in <module>\r\n    rv.main()\r\n  File \"/opt/conda/lib/python3.6/site-packages/click/core.py\", line 722, in __call__\r\n    return self.main(*args, **kwargs)\r\n  File \"/opt/conda/lib/python3.6/site-packages/click/core.py\", line 697, in main\r\n    rv = self.invoke(ctx)\r\n  File \"/opt/conda/lib/python3.6/site-packages/click/core.py\", line 1066, in invoke\r\n    return _process_result(sub_ctx.command.invoke(sub_ctx))\r\n  File \"/opt/conda/lib/python3.6/site-packages/click/core.py\", line 895, in invoke\r\n    return ctx.invoke(self.callback, **ctx.params)\r\n  File \"/opt/conda/lib/python3.6/site-packages/click/core.py\", line 535, in invoke\r\n    return callback(*args, **kwargs)\r\n  File \"/opt/src/rastervision/cli/main.py\", line 294, in run_command\r\n    rv.runner.CommandRunner.run(command_config_uri)\r\n  File \"/opt/src/rastervision/runner/command_runner.py\", line 11, in run\r\n    CommandRunner.run_from_proto(msg)\r\n  File \"/opt/src/rastervision/runner/command_runner.py\", line 17, in run_from_proto\r\n    command.run()\r\n  File \"/opt/src/rastervision/command/chip_command.py\", line 29, in run\r\n    task.make_chips(train_scenes, val_scenes, augmentors, tmp_dir)\r\n  File \"/opt/src/rastervision/task/task.py\", line 127, in make_chips\r\n    train_scenes, TRAIN, augment=True)\r\n  File \"/opt/src/rastervision/task/task.py\", line 124, in _process_scenes\r\n    return [_process_scene(scene, type_, augment) for scene in scenes]\r\n  File \"/opt/src/rastervision/task/task.py\", line 124, in <listcomp>\r\n    return [_process_scene(scene, type_, augment) for scene in scenes]\r\n  File \"/opt/src/rastervision/task/task.py\", line 107, in _process_scene\r\n    windows = self.get_train_windows(scene)\r\n  File \"/opt/src/rastervision/task/object_detection.py\", line 107, in get_train_windows\r\n    self.config.chip_options.label_buffer))\r\n  File \"/opt/src/rastervision/task/object_detection.py\", line 58, in make_pos_windows\r\n    return _make_chip_pos_windows(image_extent, label_store, chip_size)\r\n  File \"/opt/src/rastervision/task/object_detection.py\", line 28, in _make_chip_pos_windows\r\n    window = box.make_random_square_container(chip_size)\r\n  File \"/opt/src/rastervision/core/box.py\", line 121, in make_random_square_container\r\n    rand_x = random.randint(lb, ub)\r\n  File \"/opt/conda/lib/python3.6/random.py\", line 221, in randint\r\n    return self.randrange(a, b+1)\r\n  File \"/opt/conda/lib/python3.6/random.py\", line 194, in randrange\r\n    raise ValueError(\"non-integer stop for randrange()\")\r\nValueError: non-integer stop for randrange()\r\n/tmp/tmpxwof2zeo/tmp_wgvukcn/Makefile:6: recipe for target '1' failed\r\n```\n", "before_files": [{"content": "import math\nimport random\n\nimport numpy as np\nfrom shapely.geometry import box as ShapelyBox\n\n\nclass BoxSizeError(ValueError):\n    pass\n\n\nclass Box():\n    \"\"\"A multi-purpose box (ie. rectangle).\"\"\"\n\n    def __init__(self, ymin, xmin, ymax, xmax):\n        \"\"\"Construct a bounding box.\n\n        Unless otherwise stated, the convention is that these coordinates are\n        in pixel coordinates and represent boxes that lie within a\n        RasterSource.\n\n        Args:\n            ymin: minimum y value (y is row)\n            xmin: minimum x value (x is column)\n            ymax: maximum y value\n            xmax: maximum x value\n\n        \"\"\"\n        self.ymin = ymin\n        self.xmin = xmin\n        self.ymax = ymax\n        self.xmax = xmax\n\n    def __eq__(self, other):\n        \"\"\"Return true if other has same coordinates.\"\"\"\n        return self.tuple_format() == other.tuple_format()\n\n    def __ne__(self, other):\n        \"\"\"Return true if other has different coordinates.\"\"\"\n        return self.tuple_format() != other.tuple_format()\n\n    def get_height(self):\n        \"\"\"Return height of Box.\"\"\"\n        return self.ymax - self.ymin\n\n    def get_width(self):\n        \"\"\"Return width of Box.\"\"\"\n        return self.xmax - self.xmin\n\n    def get_area(self):\n        \"\"\"Return area of Box.\"\"\"\n        return self.get_height() * self.get_width()\n\n    def rasterio_format(self):\n        \"\"\"Return Box in Rasterio format.\"\"\"\n        return ((self.ymin, self.ymax), (self.xmin, self.xmax))\n\n    def tuple_format(self):\n        return (self.ymin, self.xmin, self.ymax, self.xmax)\n\n    def shapely_format(self):\n        return (self.xmin, self.ymin, self.xmax, self.ymax)\n\n    def to_int(self):\n        return Box(\n            int(self.ymin), int(self.xmin), int(self.ymax), int(self.xmax))\n\n    def npbox_format(self):\n        \"\"\"Return Box in npbox format used by TF Object Detection API.\n\n        Returns:\n            Numpy array of form [ymin, xmin, ymax, xmax] with float type\n\n        \"\"\"\n        return np.array(\n            [self.ymin, self.xmin, self.ymax, self.xmax], dtype=np.float)\n\n    @staticmethod\n    def to_npboxes(boxes):\n        \"\"\"Return nx4 numpy array from list of Box.\"\"\"\n        nb_boxes = len(boxes)\n        npboxes = np.empty((nb_boxes, 4))\n        for boxind, box in enumerate(boxes):\n            npboxes[boxind, :] = box.npbox_format()\n        return npboxes\n\n    def __str__(self):  # pragma: no cover\n        return str(self.npbox_format())\n\n    def __repr__(self):  # pragma: no cover\n        return str(self)\n\n    def geojson_coordinates(self):\n        \"\"\"Return Box as GeoJSON coordinates.\"\"\"\n        # Compass directions:\n        nw = [self.xmin, self.ymin]\n        ne = [self.xmin, self.ymax]\n        se = [self.xmax, self.ymax]\n        sw = [self.xmax, self.ymin]\n        return [nw, ne, se, sw, nw]\n\n    def make_random_square_container(self, size):\n        \"\"\"Return a new square Box that contains this Box.\n\n        Args:\n            size: the width and height of the new Box\n\n        \"\"\"\n        if size < self.get_width():\n            raise BoxSizeError('size of random container cannot be < width')\n\n        if size < self.get_height():  # pragma: no cover\n            raise BoxSizeError('size of random container cannot be < height')\n\n        lb = self.ymin - (size - self.get_height())\n        ub = self.ymin\n        rand_y = random.randint(lb, ub)\n\n        lb = self.xmin - (size - self.get_width())\n        ub = self.xmin\n        rand_x = random.randint(lb, ub)\n\n        return Box.make_square(rand_y, rand_x, size)\n\n    def make_random_square(self, size):\n        \"\"\"Return new randomly positioned square Box that lies inside this Box.\n\n        Args:\n            size: the height and width of the new Box\n\n        \"\"\"\n        if size >= self.get_width():\n            raise BoxSizeError('size of random square cannot be >= width')\n\n        if size >= self.get_height():  # pragma: no cover\n            raise BoxSizeError('size of random square cannot be >= height')\n\n        lb = self.ymin\n        ub = self.ymax - size\n        rand_y = random.randint(lb, ub)\n\n        lb = self.xmin\n        ub = self.xmax - size\n        rand_x = random.randint(lb, ub)\n\n        return Box.make_square(rand_y, rand_x, size)\n\n    def intersection(self, other):\n        \"\"\"Return the intersection of this Box and the other.\n\n        Args:\n            other: The box to intersect with this one.\n\n        Returns:\n             The intersection of this box and the other one.\n\n        \"\"\"\n        xmin = max(self.xmin, other.xmin)\n        ymin = max(self.ymin, other.ymin)\n        xmax = min(self.xmax, other.xmax)\n        ymax = min(self.ymax, other.ymax)\n        return Box(xmin=xmin, ymin=ymin, xmax=xmax, ymax=ymax)\n\n    @staticmethod\n    def from_npbox(npbox):\n        \"\"\"Return new Box based on npbox format.\n\n        Args:\n            npbox: Numpy array of form [ymin, xmin, ymax, xmax] with float type\n\n        \"\"\"\n        return Box(*npbox)\n\n    @staticmethod\n    def from_shapely(shape):\n        bounds = shape.bounds\n        return Box(bounds[1], bounds[0], bounds[3], bounds[2])\n\n    @staticmethod\n    def from_tuple(tup):\n        \"\"\"Return new Box based on tuple format.\n\n        Args:\n           tup: Tuple format box (ymin, xmin, ymax, xmax)\n        \"\"\"\n        return Box(tup[0], tup[1], tup[2], tup[3])\n\n    def to_shapely(self):\n        return ShapelyBox(*(self.shapely_format()))\n\n    def reproject(self, transform_fn):\n        \"\"\"Reprojects this box based on a transform function.\n\n        Args:\n          transform_fn - A function that takes in a tuple (x, y)\n                         and reprojects that point to the target\n                         coordinate reference system.\n        \"\"\"\n        (xmin, ymin) = transform_fn((self.xmin, self.ymin))\n        (xmax, ymax) = transform_fn((self.xmax, self.ymax))\n\n        return Box(ymin, xmin, ymax, xmax)\n\n    @staticmethod\n    def make_square(ymin, xmin, size):\n        \"\"\"Return new square Box.\"\"\"\n        return Box(ymin, xmin, ymin + size, xmin + size)\n\n    def make_eroded(self, erosion_size):\n        \"\"\"Return new Box whose sides are eroded by erosion_size.\"\"\"\n        return Box(self.ymin + erosion_size, self.xmin + erosion_size,\n                   self.ymax - erosion_size, self.xmax - erosion_size)\n\n    def make_buffer(self, buffer_size, max_extent):\n        \"\"\"Return new Box whose sides are buffered by buffer_size.\n\n        The resulting box is clipped so that the values of the corners are\n        always greater than zero and less than the height and width of\n        max_extent.\n\n        \"\"\"\n        buffer_size = max(0., buffer_size)\n        if buffer_size < 1.:\n            delta_width = int(round(buffer_size * self.get_width()))\n            delta_height = int(round(buffer_size * self.get_height()))\n        else:\n            delta_height = delta_width = int(round(buffer_size))\n\n        return Box(\n            max(0, math.floor(self.ymin - delta_height)),\n            max(0, math.floor(self.xmin - delta_width)),\n            min(max_extent.get_height(),\n                int(self.ymax) + delta_height),\n            min(max_extent.get_width(),\n                int(self.xmax) + delta_width))\n\n    def make_copy(self):\n        return Box(*(self.tuple_format()))\n\n    def get_windows(self, chip_size, stride):\n        \"\"\"Return list of grid of boxes within this box.\n\n        Args:\n            chip_size: (int) the length of each square-shaped window in pixels\n            stride: (int) how much each window is offset from the last in pixels\n\n        \"\"\"\n        height = self.get_height()\n        width = self.get_width()\n\n        result = []\n        for row_start in range(0, height, stride):\n            for col_start in range(0, width, stride):\n                result.append(Box.make_square(row_start, col_start, chip_size))\n        return result\n\n    def to_dict(self):\n        return {\n            'xmin': self.xmin,\n            'ymin': self.ymin,\n            'xmax': self.xmax,\n            'ymax': self.ymax\n        }\n\n    @classmethod\n    def from_dict(cls, d):\n        return cls(d['ymin'], d['xmin'], d['ymax'], d['xmax'])\n\n    @staticmethod\n    def filter_by_aoi(windows, aoi_polygons):\n        \"\"\"Filters windows by a list of AOI polygons\"\"\"\n        result = []\n        for window in windows:\n            w = window.to_shapely()\n            for polygon in aoi_polygons:\n                if w.within(polygon):\n                    result.append(window)\n                    break\n\n        return result\n", "path": "rastervision/core/box.py"}], "after_files": [{"content": "import math\nimport random\n\nimport numpy as np\nfrom shapely.geometry import box as ShapelyBox\n\n\nclass BoxSizeError(ValueError):\n    pass\n\n\nclass Box():\n    \"\"\"A multi-purpose box (ie. rectangle).\"\"\"\n\n    def __init__(self, ymin, xmin, ymax, xmax):\n        \"\"\"Construct a bounding box.\n\n        Unless otherwise stated, the convention is that these coordinates are\n        in pixel coordinates and represent boxes that lie within a\n        RasterSource.\n\n        Args:\n            ymin: minimum y value (y is row)\n            xmin: minimum x value (x is column)\n            ymax: maximum y value\n            xmax: maximum x value\n\n        \"\"\"\n        self.ymin = ymin\n        self.xmin = xmin\n        self.ymax = ymax\n        self.xmax = xmax\n\n    def __eq__(self, other):\n        \"\"\"Return true if other has same coordinates.\"\"\"\n        return self.tuple_format() == other.tuple_format()\n\n    def __ne__(self, other):\n        \"\"\"Return true if other has different coordinates.\"\"\"\n        return self.tuple_format() != other.tuple_format()\n\n    def get_height(self):\n        \"\"\"Return height of Box.\"\"\"\n        return self.ymax - self.ymin\n\n    def get_width(self):\n        \"\"\"Return width of Box.\"\"\"\n        return self.xmax - self.xmin\n\n    def get_area(self):\n        \"\"\"Return area of Box.\"\"\"\n        return self.get_height() * self.get_width()\n\n    def rasterio_format(self):\n        \"\"\"Return Box in Rasterio format.\"\"\"\n        return ((self.ymin, self.ymax), (self.xmin, self.xmax))\n\n    def tuple_format(self):\n        return (self.ymin, self.xmin, self.ymax, self.xmax)\n\n    def shapely_format(self):\n        return (self.xmin, self.ymin, self.xmax, self.ymax)\n\n    def to_int(self):\n        return Box(\n            int(self.ymin), int(self.xmin), int(self.ymax), int(self.xmax))\n\n    def npbox_format(self):\n        \"\"\"Return Box in npbox format used by TF Object Detection API.\n\n        Returns:\n            Numpy array of form [ymin, xmin, ymax, xmax] with float type\n\n        \"\"\"\n        return np.array(\n            [self.ymin, self.xmin, self.ymax, self.xmax], dtype=np.float)\n\n    @staticmethod\n    def to_npboxes(boxes):\n        \"\"\"Return nx4 numpy array from list of Box.\"\"\"\n        nb_boxes = len(boxes)\n        npboxes = np.empty((nb_boxes, 4))\n        for boxind, box in enumerate(boxes):\n            npboxes[boxind, :] = box.npbox_format()\n        return npboxes\n\n    def __str__(self):  # pragma: no cover\n        return str(self.npbox_format())\n\n    def __repr__(self):  # pragma: no cover\n        return str(self)\n\n    def geojson_coordinates(self):\n        \"\"\"Return Box as GeoJSON coordinates.\"\"\"\n        # Compass directions:\n        nw = [self.xmin, self.ymin]\n        ne = [self.xmin, self.ymax]\n        se = [self.xmax, self.ymax]\n        sw = [self.xmax, self.ymin]\n        return [nw, ne, se, sw, nw]\n\n    def make_random_square_container(self, size):\n        \"\"\"Return a new square Box that contains this Box.\n\n        Args:\n            size: the width and height of the new Box\n\n        \"\"\"\n        if size < self.get_width():\n            raise BoxSizeError('size of random container cannot be < width')\n\n        if size < self.get_height():  # pragma: no cover\n            raise BoxSizeError('size of random container cannot be < height')\n\n        lb = self.ymin - (size - self.get_height())\n        ub = self.ymin\n        rand_y = random.randint(int(lb), int(ub))\n\n        lb = self.xmin - (size - self.get_width())\n        ub = self.xmin\n        rand_x = random.randint(int(lb), int(ub))\n\n        return Box.make_square(rand_y, rand_x, size)\n\n    def make_random_square(self, size):\n        \"\"\"Return new randomly positioned square Box that lies inside this Box.\n\n        Args:\n            size: the height and width of the new Box\n\n        \"\"\"\n        if size >= self.get_width():\n            raise BoxSizeError('size of random square cannot be >= width')\n\n        if size >= self.get_height():  # pragma: no cover\n            raise BoxSizeError('size of random square cannot be >= height')\n\n        lb = self.ymin\n        ub = self.ymax - size\n        rand_y = random.randint(int(lb), int(ub))\n\n        lb = self.xmin\n        ub = self.xmax - size\n        rand_x = random.randint(int(lb), int(ub))\n\n        return Box.make_square(rand_y, rand_x, size)\n\n    def intersection(self, other):\n        \"\"\"Return the intersection of this Box and the other.\n\n        Args:\n            other: The box to intersect with this one.\n\n        Returns:\n             The intersection of this box and the other one.\n\n        \"\"\"\n        xmin = max(self.xmin, other.xmin)\n        ymin = max(self.ymin, other.ymin)\n        xmax = min(self.xmax, other.xmax)\n        ymax = min(self.ymax, other.ymax)\n        return Box(xmin=xmin, ymin=ymin, xmax=xmax, ymax=ymax)\n\n    @staticmethod\n    def from_npbox(npbox):\n        \"\"\"Return new Box based on npbox format.\n\n        Args:\n            npbox: Numpy array of form [ymin, xmin, ymax, xmax] with float type\n\n        \"\"\"\n        return Box(*npbox)\n\n    @staticmethod\n    def from_shapely(shape):\n        bounds = shape.bounds\n        return Box(bounds[1], bounds[0], bounds[3], bounds[2])\n\n    @staticmethod\n    def from_tuple(tup):\n        \"\"\"Return new Box based on tuple format.\n\n        Args:\n           tup: Tuple format box (ymin, xmin, ymax, xmax)\n        \"\"\"\n        return Box(tup[0], tup[1], tup[2], tup[3])\n\n    def to_shapely(self):\n        return ShapelyBox(*(self.shapely_format()))\n\n    def reproject(self, transform_fn):\n        \"\"\"Reprojects this box based on a transform function.\n\n        Args:\n          transform_fn - A function that takes in a tuple (x, y)\n                         and reprojects that point to the target\n                         coordinate reference system.\n        \"\"\"\n        (xmin, ymin) = transform_fn((self.xmin, self.ymin))\n        (xmax, ymax) = transform_fn((self.xmax, self.ymax))\n\n        return Box(ymin, xmin, ymax, xmax)\n\n    @staticmethod\n    def make_square(ymin, xmin, size):\n        \"\"\"Return new square Box.\"\"\"\n        return Box(ymin, xmin, ymin + size, xmin + size)\n\n    def make_eroded(self, erosion_size):\n        \"\"\"Return new Box whose sides are eroded by erosion_size.\"\"\"\n        return Box(self.ymin + erosion_size, self.xmin + erosion_size,\n                   self.ymax - erosion_size, self.xmax - erosion_size)\n\n    def make_buffer(self, buffer_size, max_extent):\n        \"\"\"Return new Box whose sides are buffered by buffer_size.\n\n        The resulting box is clipped so that the values of the corners are\n        always greater than zero and less than the height and width of\n        max_extent.\n\n        \"\"\"\n        buffer_size = max(0., buffer_size)\n        if buffer_size < 1.:\n            delta_width = int(round(buffer_size * self.get_width()))\n            delta_height = int(round(buffer_size * self.get_height()))\n        else:\n            delta_height = delta_width = int(round(buffer_size))\n\n        return Box(\n            max(0, math.floor(self.ymin - delta_height)),\n            max(0, math.floor(self.xmin - delta_width)),\n            min(max_extent.get_height(),\n                int(self.ymax) + delta_height),\n            min(max_extent.get_width(),\n                int(self.xmax) + delta_width))\n\n    def make_copy(self):\n        return Box(*(self.tuple_format()))\n\n    def get_windows(self, chip_size, stride):\n        \"\"\"Return list of grid of boxes within this box.\n\n        Args:\n            chip_size: (int) the length of each square-shaped window in pixels\n            stride: (int) how much each window is offset from the last in pixels\n\n        \"\"\"\n        height = self.get_height()\n        width = self.get_width()\n\n        result = []\n        for row_start in range(0, height, stride):\n            for col_start in range(0, width, stride):\n                result.append(Box.make_square(row_start, col_start, chip_size))\n        return result\n\n    def to_dict(self):\n        return {\n            'xmin': self.xmin,\n            'ymin': self.ymin,\n            'xmax': self.xmax,\n            'ymax': self.ymax\n        }\n\n    @classmethod\n    def from_dict(cls, d):\n        return cls(d['ymin'], d['xmin'], d['ymax'], d['xmax'])\n\n    @staticmethod\n    def filter_by_aoi(windows, aoi_polygons):\n        \"\"\"Filters windows by a list of AOI polygons\"\"\"\n        result = []\n        for window in windows:\n            w = window.to_shapely()\n            for polygon in aoi_polygons:\n                if w.within(polygon):\n                    result.append(window)\n                    break\n\n        return result\n", "path": "rastervision/core/box.py"}]}