We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Not able to use default stride with sliding window semseg option


--- 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/task/semantic_segmentation_config.py`
Content:
```
1 from copy import deepcopy
2 from typing import (List, Dict, Tuple, Union)
3 
4 import rastervision as rv
5 from rastervision.task import SemanticSegmentation
6 from rastervision.core.class_map import (ClassMap, ClassItem)
7 from rastervision.task import (TaskConfig, TaskConfigBuilder)
8 from rastervision.protos.task_pb2 import TaskConfig as TaskConfigMsg
9 from rastervision.protos.class_item_pb2 import ClassItem as ClassItemMsg
10 
11 
12 class SemanticSegmentationConfig(TaskConfig):
13     class ChipOptions:
14         def __init__(self,
15                      window_method='random_sample',
16                      target_classes=None,
17                      debug_chip_probability=0.25,
18                      negative_survival_probability=1.0,
19                      chips_per_scene=1000,
20                      target_count_threshold=1000,
21                      stride=None):
22             self.window_method = window_method
23             self.target_classes = target_classes
24             self.debug_chip_probability = debug_chip_probability
25             self.negative_survival_probability = negative_survival_probability
26             self.chips_per_scene = chips_per_scene
27             self.target_count_threshold = target_count_threshold
28             self.stride = stride
29 
30     def __init__(self,
31                  class_map,
32                  predict_batch_size=10,
33                  predict_package_uri=None,
34                  debug=True,
35                  chip_size=300,
36                  chip_options=None):
37         super().__init__(rv.SEMANTIC_SEGMENTATION, predict_batch_size,
38                          predict_package_uri, debug)
39         self.class_map = class_map
40         self.chip_size = chip_size
41         if chip_options is None:
42             chip_options = SemanticSegmentationConfig.ChipOptions()
43         self.chip_options = chip_options
44 
45     def save_bundle_files(self, bundle_dir):
46         return (self, [])
47 
48     def load_bundle_files(self, bundle_dir):
49         return self
50 
51     def create_task(self, backend):
52         return SemanticSegmentation(self, backend)
53 
54     def to_proto(self):
55         msg = super().to_proto()
56         chip_options = TaskConfigMsg.SemanticSegmentationConfig.ChipOptions(
57             window_method=self.chip_options.window_method,
58             target_classes=self.chip_options.target_classes,
59             debug_chip_probability=self.chip_options.debug_chip_probability,
60             negative_survival_probability=self.chip_options.
61             negative_survival_probability,
62             chips_per_scene=self.chip_options.chips_per_scene,
63             target_count_threshold=self.chip_options.target_count_threshold,
64             stride=self.chip_options.stride)
65 
66         conf = TaskConfigMsg.SemanticSegmentationConfig(
67             chip_size=self.chip_size,
68             class_items=self.class_map.to_proto(),
69             chip_options=chip_options)
70         msg.MergeFrom(
71             TaskConfigMsg(
72                 semantic_segmentation_config=conf,
73                 predict_package_uri=self.predict_package_uri))
74 
75         return msg
76 
77 
78 class SemanticSegmentationConfigBuilder(TaskConfigBuilder):
79     def __init__(self, prev=None):
80         config = {}
81         if prev:
82             config = {
83                 'predict_batch_size': prev.predict_batch_size,
84                 'predict_package_uri': prev.predict_package_uri,
85                 'debug': prev.debug,
86                 'class_map': prev.class_map,
87                 'chip_size': prev.chip_size,
88                 'chip_options': prev.chip_options
89             }
90         super().__init__(SemanticSegmentationConfig, config)
91 
92     def from_proto(self, msg):
93         conf = msg.semantic_segmentation_config
94 
95         negative_survival_probability = conf.chip_options \
96                                             .negative_survival_probability
97 
98         return self.with_classes(list(conf.class_items)) \
99                 .with_predict_batch_size(msg.predict_batch_size) \
100                 .with_predict_package_uri(msg.predict_package_uri) \
101                 .with_debug(msg.debug) \
102                 .with_chip_size(conf.chip_size) \
103                 .with_chip_options(
104                     window_method=conf.chip_options.window_method,
105                     target_classes=list(conf.chip_options.target_classes),
106                     debug_chip_probability=conf.chip_options.debug_chip_probability,
107                     negative_survival_probability=negative_survival_probability,
108                     chips_per_scene=conf.chip_options.chips_per_scene,
109                     target_count_threshold=conf.chip_options.target_count_threshold,
110                     stride=conf.chip_options.stride)
111 
112     def validate(self):
113         super().validate()
114         # Segmentation masks are stored as uint8 to save space, so can only handle 256
115         # classes. If this is really needed, we can add an option for saving with uint16.
116         max_classes = 256
117         if len(self.config['class_map']) > max_classes:
118             raise rv.ConfigError(
119                 'Cannot use more than {} classes with semantic segmentation.'.
120                 format(max_classes))
121 
122     def with_classes(
123             self, classes: Union[ClassMap, List[str], List[ClassItemMsg], List[
124                 ClassItem], Dict[str, int], Dict[str, Tuple[int, str]]]):
125         """Set the classes for this task.
126 
127             Args:
128                 classes: Either a list of class names, a dict which
129                          maps class names to class ids, or a dict
130                          which maps class names to a tuple of (class_id, color),
131                          where color is a PIL color string.
132         """
133         b = deepcopy(self)
134         b.config['class_map'] = ClassMap.construct_from(classes)
135         return b
136 
137     def with_chip_size(self, chip_size):
138         """Set the chip_size for this task.
139 
140             Args:
141                 chip_size: Integer value chip size
142         """
143         b = deepcopy(self)
144         b.config['chip_size'] = chip_size
145         return b
146 
147     def with_chip_options(self,
148                           window_method='random_sample',
149                           target_classes=None,
150                           debug_chip_probability=0.25,
151                           negative_survival_probability=1.0,
152                           chips_per_scene=1000,
153                           target_count_threshold=1000,
154                           stride=None):
155         """Sets semantic segmentation configurations for the Chip command
156 
157            Args:
158             window_method: Window method to use for chipping.
159                            Options are: random_sample, sliding
160             target_classes: list of class ids to train model on
161             debug_chip_probability: probability of generating a debug chip.
162                                     Applies to the 'random_sample' window method.
163             negative_survival_probability: probability that a sampled negative
164                                            chip will be utilized if it does not
165                                            contain more pixels than
166                                            target_count_threshold.
167                                            Applies to the 'random_sample' window method.
168             chips_per_scene: number of chips to generate per scene.
169                              Applies to the 'random_sample' window method.
170             target_count_threshold: minimum number of pixels covering target_classes
171                                     that a chip must have.
172                                     Applies to the 'random_sample' window method.
173             stride: Stride of windows across image. Defaults to half the chip size.
174                     Applies to the 'sliding_window' method.
175 
176         Returns:
177             SemanticSegmentationConfigBuilder
178         """
179         b = deepcopy(self)
180 
181         b.config['chip_options'] = SemanticSegmentationConfig.ChipOptions(
182             window_method=window_method,
183             target_classes=target_classes,
184             debug_chip_probability=debug_chip_probability,
185             negative_survival_probability=negative_survival_probability,
186             chips_per_scene=chips_per_scene,
187             target_count_threshold=target_count_threshold,
188             stride=stride)
189         return b
190
```

Path: `rastervision/task/semantic_segmentation.py`
Content:
```
1 from typing import List
2 import logging
3 
4 import numpy as np
5 
6 from .task import Task
7 from rastervision.core.box import Box
8 from rastervision.data.scene import Scene
9 from rastervision.data.label import SemanticSegmentationLabels
10 
11 log = logging.getLogger(__name__)
12 
13 
14 def get_random_sample_train_windows(label_store, chip_size, class_map, extent,
15                                     chip_options, filter_windows):
16     prob = chip_options.negative_survival_probability
17     target_count_threshold = chip_options.target_count_threshold
18     target_classes = chip_options.target_classes
19     chips_per_scene = chip_options.chips_per_scene
20 
21     if not target_classes:
22         all_class_ids = [item.id for item in class_map.get_items()]
23         target_classes = all_class_ids
24 
25     windows = []
26     attempts = 0
27     while (attempts < chips_per_scene):
28         candidate_window = extent.make_random_square(chip_size)
29         if not filter_windows([candidate_window]):
30             continue
31         attempts = attempts + 1
32 
33         if (prob >= 1.0):
34             windows.append(candidate_window)
35         elif attempts == chips_per_scene and len(windows) == 0:
36             windows.append(candidate_window)
37         else:
38             good = label_store.enough_target_pixels(
39                 candidate_window, target_count_threshold, target_classes)
40             if good or (np.random.rand() < prob):
41                 windows.append(candidate_window)
42 
43     return windows
44 
45 
46 class SemanticSegmentation(Task):
47     """Task-derived type that implements the semantic segmentation task."""
48 
49     def get_train_windows(self, scene: Scene) -> List[Box]:
50         """Get training windows covering a scene.
51 
52         Args:
53              scene: The scene over-which windows are to be generated.
54 
55         Returns:
56              A list of windows, list(Box)
57 
58         """
59 
60         def filter_windows(windows):
61             if scene.aoi_polygons:
62                 windows = Box.filter_by_aoi(windows, scene.aoi_polygons)
63             return windows
64 
65         raster_source = scene.raster_source
66         extent = raster_source.get_extent()
67         label_store = scene.ground_truth_label_source
68         chip_size = self.config.chip_size
69 
70         chip_options = self.config.chip_options
71 
72         if chip_options.window_method == 'random_sample':
73             return get_random_sample_train_windows(
74                 label_store, chip_size, self.config.class_map, extent,
75                 chip_options, filter_windows)
76         elif chip_options.window_method == 'sliding':
77             stride = chip_options.stride
78             if stride is None:
79                 stride = chip_size / 2
80 
81             return list(
82                 filter_windows((extent.get_windows(chip_size, stride))))
83 
84     def get_train_labels(self, window: Box, scene: Scene) -> np.ndarray:
85         """Get the training labels for the given window in the given scene.
86 
87         Args:
88              window: The window over-which the labels are to be
89                   retrieved.
90              scene: The scene from-which the window of labels is to be
91                   extracted.
92 
93         Returns:
94              An appropriately-shaped 2d np.ndarray with the labels
95              encoded as packed pixels.
96 
97         """
98         label_store = scene.ground_truth_label_source
99         return label_store.get_labels(window)
100 
101     def get_predict_windows(self, extent: Box) -> List[Box]:
102         """Get windows over-which predictions will be calculated.
103 
104         Args:
105              extent: The overall extent of the area.
106 
107         Returns:
108              An sequence of windows.
109 
110         """
111         chip_size = self.config.chip_size
112         return extent.get_windows(chip_size, chip_size)
113 
114     def post_process_predictions(self, labels, scene):
115         return labels
116 
117     def save_debug_predict_image(self, scene, debug_dir_uri):
118         # TODO implement this
119         pass
120 
121     def predict_scene(self, scene, tmp_dir):
122         """Predict on a single scene, and return the labels."""
123         log.info('Making predictions for scene')
124         raster_source = scene.raster_source
125         windows = self.get_predict_windows(raster_source.get_extent())
126 
127         def label_fn(window):
128             chip = raster_source.get_chip(window)
129             labels = self.backend.predict([chip], [window], tmp_dir)
130             label_arr = labels.get_label_arr(window)
131 
132             # Set NODATA pixels in imagery to predicted value of 0 (ie. ignore)
133             label_arr[np.sum(chip, axis=2) == 0] = 0
134 
135             print('.', end='', flush=True)
136             return label_arr
137 
138         return SemanticSegmentationLabels(windows, label_fn)
139
```
--- 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/task/semantic_segmentation.py b/rastervision/task/semantic_segmentation.py
--- a/rastervision/task/semantic_segmentation.py
+++ b/rastervision/task/semantic_segmentation.py
@@ -77,6 +77,7 @@
             stride = chip_options.stride
             if stride is None:
                 stride = chip_size / 2
+            stride = int(round(stride))
 
             return list(
                 filter_windows((extent.get_windows(chip_size, stride))))
diff --git a/rastervision/task/semantic_segmentation_config.py b/rastervision/task/semantic_segmentation_config.py
--- a/rastervision/task/semantic_segmentation_config.py
+++ b/rastervision/task/semantic_segmentation_config.py
@@ -95,6 +95,10 @@
         negative_survival_probability = conf.chip_options \
                                             .negative_survival_probability
 
+        stride = conf.chip_options.stride
+        if stride == 0:
+            stride = None
+
         return self.with_classes(list(conf.class_items)) \
                 .with_predict_batch_size(msg.predict_batch_size) \
                 .with_predict_package_uri(msg.predict_package_uri) \
@@ -107,7 +111,7 @@
                     negative_survival_probability=negative_survival_probability,
                     chips_per_scene=conf.chip_options.chips_per_scene,
                     target_count_threshold=conf.chip_options.target_count_threshold,
-                    stride=conf.chip_options.stride)
+                    stride=stride)
 
     def validate(self):
         super().validate()

{"golden_diff": "diff --git a/rastervision/task/semantic_segmentation.py b/rastervision/task/semantic_segmentation.py\n--- a/rastervision/task/semantic_segmentation.py\n+++ b/rastervision/task/semantic_segmentation.py\n@@ -77,6 +77,7 @@\n             stride = chip_options.stride\n             if stride is None:\n                 stride = chip_size / 2\n+            stride = int(round(stride))\n \n             return list(\n                 filter_windows((extent.get_windows(chip_size, stride))))\ndiff --git a/rastervision/task/semantic_segmentation_config.py b/rastervision/task/semantic_segmentation_config.py\n--- a/rastervision/task/semantic_segmentation_config.py\n+++ b/rastervision/task/semantic_segmentation_config.py\n@@ -95,6 +95,10 @@\n         negative_survival_probability = conf.chip_options \\\n                                             .negative_survival_probability\n \n+        stride = conf.chip_options.stride\n+        if stride == 0:\n+            stride = None\n+\n         return self.with_classes(list(conf.class_items)) \\\n                 .with_predict_batch_size(msg.predict_batch_size) \\\n                 .with_predict_package_uri(msg.predict_package_uri) \\\n@@ -107,7 +111,7 @@\n                     negative_survival_probability=negative_survival_probability,\n                     chips_per_scene=conf.chip_options.chips_per_scene,\n                     target_count_threshold=conf.chip_options.target_count_threshold,\n-                    stride=conf.chip_options.stride)\n+                    stride=stride)\n \n     def validate(self):\n         super().validate()\n", "issue": "Not able to use default stride with sliding window semseg option\n\n", "before_files": [{"content": "from copy import deepcopy\nfrom typing import (List, Dict, Tuple, Union)\n\nimport rastervision as rv\nfrom rastervision.task import SemanticSegmentation\nfrom rastervision.core.class_map import (ClassMap, ClassItem)\nfrom rastervision.task import (TaskConfig, TaskConfigBuilder)\nfrom rastervision.protos.task_pb2 import TaskConfig as TaskConfigMsg\nfrom rastervision.protos.class_item_pb2 import ClassItem as ClassItemMsg\n\n\nclass SemanticSegmentationConfig(TaskConfig):\n    class ChipOptions:\n        def __init__(self,\n                     window_method='random_sample',\n                     target_classes=None,\n                     debug_chip_probability=0.25,\n                     negative_survival_probability=1.0,\n                     chips_per_scene=1000,\n                     target_count_threshold=1000,\n                     stride=None):\n            self.window_method = window_method\n            self.target_classes = target_classes\n            self.debug_chip_probability = debug_chip_probability\n            self.negative_survival_probability = negative_survival_probability\n            self.chips_per_scene = chips_per_scene\n            self.target_count_threshold = target_count_threshold\n            self.stride = stride\n\n    def __init__(self,\n                 class_map,\n                 predict_batch_size=10,\n                 predict_package_uri=None,\n                 debug=True,\n                 chip_size=300,\n                 chip_options=None):\n        super().__init__(rv.SEMANTIC_SEGMENTATION, predict_batch_size,\n                         predict_package_uri, debug)\n        self.class_map = class_map\n        self.chip_size = chip_size\n        if chip_options is None:\n            chip_options = SemanticSegmentationConfig.ChipOptions()\n        self.chip_options = chip_options\n\n    def save_bundle_files(self, bundle_dir):\n        return (self, [])\n\n    def load_bundle_files(self, bundle_dir):\n        return self\n\n    def create_task(self, backend):\n        return SemanticSegmentation(self, backend)\n\n    def to_proto(self):\n        msg = super().to_proto()\n        chip_options = TaskConfigMsg.SemanticSegmentationConfig.ChipOptions(\n            window_method=self.chip_options.window_method,\n            target_classes=self.chip_options.target_classes,\n            debug_chip_probability=self.chip_options.debug_chip_probability,\n            negative_survival_probability=self.chip_options.\n            negative_survival_probability,\n            chips_per_scene=self.chip_options.chips_per_scene,\n            target_count_threshold=self.chip_options.target_count_threshold,\n            stride=self.chip_options.stride)\n\n        conf = TaskConfigMsg.SemanticSegmentationConfig(\n            chip_size=self.chip_size,\n            class_items=self.class_map.to_proto(),\n            chip_options=chip_options)\n        msg.MergeFrom(\n            TaskConfigMsg(\n                semantic_segmentation_config=conf,\n                predict_package_uri=self.predict_package_uri))\n\n        return msg\n\n\nclass SemanticSegmentationConfigBuilder(TaskConfigBuilder):\n    def __init__(self, prev=None):\n        config = {}\n        if prev:\n            config = {\n                'predict_batch_size': prev.predict_batch_size,\n                'predict_package_uri': prev.predict_package_uri,\n                'debug': prev.debug,\n                'class_map': prev.class_map,\n                'chip_size': prev.chip_size,\n                'chip_options': prev.chip_options\n            }\n        super().__init__(SemanticSegmentationConfig, config)\n\n    def from_proto(self, msg):\n        conf = msg.semantic_segmentation_config\n\n        negative_survival_probability = conf.chip_options \\\n                                            .negative_survival_probability\n\n        return self.with_classes(list(conf.class_items)) \\\n                .with_predict_batch_size(msg.predict_batch_size) \\\n                .with_predict_package_uri(msg.predict_package_uri) \\\n                .with_debug(msg.debug) \\\n                .with_chip_size(conf.chip_size) \\\n                .with_chip_options(\n                    window_method=conf.chip_options.window_method,\n                    target_classes=list(conf.chip_options.target_classes),\n                    debug_chip_probability=conf.chip_options.debug_chip_probability,\n                    negative_survival_probability=negative_survival_probability,\n                    chips_per_scene=conf.chip_options.chips_per_scene,\n                    target_count_threshold=conf.chip_options.target_count_threshold,\n                    stride=conf.chip_options.stride)\n\n    def validate(self):\n        super().validate()\n        # Segmentation masks are stored as uint8 to save space, so can only handle 256\n        # classes. If this is really needed, we can add an option for saving with uint16.\n        max_classes = 256\n        if len(self.config['class_map']) > max_classes:\n            raise rv.ConfigError(\n                'Cannot use more than {} classes with semantic segmentation.'.\n                format(max_classes))\n\n    def with_classes(\n            self, classes: Union[ClassMap, List[str], List[ClassItemMsg], List[\n                ClassItem], Dict[str, int], Dict[str, Tuple[int, str]]]):\n        \"\"\"Set the classes for this task.\n\n            Args:\n                classes: Either a list of class names, a dict which\n                         maps class names to class ids, or a dict\n                         which maps class names to a tuple of (class_id, color),\n                         where color is a PIL color string.\n        \"\"\"\n        b = deepcopy(self)\n        b.config['class_map'] = ClassMap.construct_from(classes)\n        return b\n\n    def with_chip_size(self, chip_size):\n        \"\"\"Set the chip_size for this task.\n\n            Args:\n                chip_size: Integer value chip size\n        \"\"\"\n        b = deepcopy(self)\n        b.config['chip_size'] = chip_size\n        return b\n\n    def with_chip_options(self,\n                          window_method='random_sample',\n                          target_classes=None,\n                          debug_chip_probability=0.25,\n                          negative_survival_probability=1.0,\n                          chips_per_scene=1000,\n                          target_count_threshold=1000,\n                          stride=None):\n        \"\"\"Sets semantic segmentation configurations for the Chip command\n\n           Args:\n            window_method: Window method to use for chipping.\n                           Options are: random_sample, sliding\n            target_classes: list of class ids to train model on\n            debug_chip_probability: probability of generating a debug chip.\n                                    Applies to the 'random_sample' window method.\n            negative_survival_probability: probability that a sampled negative\n                                           chip will be utilized if it does not\n                                           contain more pixels than\n                                           target_count_threshold.\n                                           Applies to the 'random_sample' window method.\n            chips_per_scene: number of chips to generate per scene.\n                             Applies to the 'random_sample' window method.\n            target_count_threshold: minimum number of pixels covering target_classes\n                                    that a chip must have.\n                                    Applies to the 'random_sample' window method.\n            stride: Stride of windows across image. Defaults to half the chip size.\n                    Applies to the 'sliding_window' method.\n\n        Returns:\n            SemanticSegmentationConfigBuilder\n        \"\"\"\n        b = deepcopy(self)\n\n        b.config['chip_options'] = SemanticSegmentationConfig.ChipOptions(\n            window_method=window_method,\n            target_classes=target_classes,\n            debug_chip_probability=debug_chip_probability,\n            negative_survival_probability=negative_survival_probability,\n            chips_per_scene=chips_per_scene,\n            target_count_threshold=target_count_threshold,\n            stride=stride)\n        return b\n", "path": "rastervision/task/semantic_segmentation_config.py"}, {"content": "from typing import List\nimport logging\n\nimport numpy as np\n\nfrom .task import Task\nfrom rastervision.core.box import Box\nfrom rastervision.data.scene import Scene\nfrom rastervision.data.label import SemanticSegmentationLabels\n\nlog = logging.getLogger(__name__)\n\n\ndef get_random_sample_train_windows(label_store, chip_size, class_map, extent,\n                                    chip_options, filter_windows):\n    prob = chip_options.negative_survival_probability\n    target_count_threshold = chip_options.target_count_threshold\n    target_classes = chip_options.target_classes\n    chips_per_scene = chip_options.chips_per_scene\n\n    if not target_classes:\n        all_class_ids = [item.id for item in class_map.get_items()]\n        target_classes = all_class_ids\n\n    windows = []\n    attempts = 0\n    while (attempts < chips_per_scene):\n        candidate_window = extent.make_random_square(chip_size)\n        if not filter_windows([candidate_window]):\n            continue\n        attempts = attempts + 1\n\n        if (prob >= 1.0):\n            windows.append(candidate_window)\n        elif attempts == chips_per_scene and len(windows) == 0:\n            windows.append(candidate_window)\n        else:\n            good = label_store.enough_target_pixels(\n                candidate_window, target_count_threshold, target_classes)\n            if good or (np.random.rand() < prob):\n                windows.append(candidate_window)\n\n    return windows\n\n\nclass SemanticSegmentation(Task):\n    \"\"\"Task-derived type that implements the semantic segmentation task.\"\"\"\n\n    def get_train_windows(self, scene: Scene) -> List[Box]:\n        \"\"\"Get training windows covering a scene.\n\n        Args:\n             scene: The scene over-which windows are to be generated.\n\n        Returns:\n             A list of windows, list(Box)\n\n        \"\"\"\n\n        def filter_windows(windows):\n            if scene.aoi_polygons:\n                windows = Box.filter_by_aoi(windows, scene.aoi_polygons)\n            return windows\n\n        raster_source = scene.raster_source\n        extent = raster_source.get_extent()\n        label_store = scene.ground_truth_label_source\n        chip_size = self.config.chip_size\n\n        chip_options = self.config.chip_options\n\n        if chip_options.window_method == 'random_sample':\n            return get_random_sample_train_windows(\n                label_store, chip_size, self.config.class_map, extent,\n                chip_options, filter_windows)\n        elif chip_options.window_method == 'sliding':\n            stride = chip_options.stride\n            if stride is None:\n                stride = chip_size / 2\n\n            return list(\n                filter_windows((extent.get_windows(chip_size, stride))))\n\n    def get_train_labels(self, window: Box, scene: Scene) -> np.ndarray:\n        \"\"\"Get the training labels for the given window in the given scene.\n\n        Args:\n             window: The window over-which the labels are to be\n                  retrieved.\n             scene: The scene from-which the window of labels is to be\n                  extracted.\n\n        Returns:\n             An appropriately-shaped 2d np.ndarray with the labels\n             encoded as packed pixels.\n\n        \"\"\"\n        label_store = scene.ground_truth_label_source\n        return label_store.get_labels(window)\n\n    def get_predict_windows(self, extent: Box) -> List[Box]:\n        \"\"\"Get windows over-which predictions will be calculated.\n\n        Args:\n             extent: The overall extent of the area.\n\n        Returns:\n             An sequence of windows.\n\n        \"\"\"\n        chip_size = self.config.chip_size\n        return extent.get_windows(chip_size, chip_size)\n\n    def post_process_predictions(self, labels, scene):\n        return labels\n\n    def save_debug_predict_image(self, scene, debug_dir_uri):\n        # TODO implement this\n        pass\n\n    def predict_scene(self, scene, tmp_dir):\n        \"\"\"Predict on a single scene, and return the labels.\"\"\"\n        log.info('Making predictions for scene')\n        raster_source = scene.raster_source\n        windows = self.get_predict_windows(raster_source.get_extent())\n\n        def label_fn(window):\n            chip = raster_source.get_chip(window)\n            labels = self.backend.predict([chip], [window], tmp_dir)\n            label_arr = labels.get_label_arr(window)\n\n            # Set NODATA pixels in imagery to predicted value of 0 (ie. ignore)\n            label_arr[np.sum(chip, axis=2) == 0] = 0\n\n            print('.', end='', flush=True)\n            return label_arr\n\n        return SemanticSegmentationLabels(windows, label_fn)\n", "path": "rastervision/task/semantic_segmentation.py"}], "after_files": [{"content": "from copy import deepcopy\nfrom typing import (List, Dict, Tuple, Union)\n\nimport rastervision as rv\nfrom rastervision.task import SemanticSegmentation\nfrom rastervision.core.class_map import (ClassMap, ClassItem)\nfrom rastervision.task import (TaskConfig, TaskConfigBuilder)\nfrom rastervision.protos.task_pb2 import TaskConfig as TaskConfigMsg\nfrom rastervision.protos.class_item_pb2 import ClassItem as ClassItemMsg\n\n\nclass SemanticSegmentationConfig(TaskConfig):\n    class ChipOptions:\n        def __init__(self,\n                     window_method='random_sample',\n                     target_classes=None,\n                     debug_chip_probability=0.25,\n                     negative_survival_probability=1.0,\n                     chips_per_scene=1000,\n                     target_count_threshold=1000,\n                     stride=None):\n            self.window_method = window_method\n            self.target_classes = target_classes\n            self.debug_chip_probability = debug_chip_probability\n            self.negative_survival_probability = negative_survival_probability\n            self.chips_per_scene = chips_per_scene\n            self.target_count_threshold = target_count_threshold\n            self.stride = stride\n\n    def __init__(self,\n                 class_map,\n                 predict_batch_size=10,\n                 predict_package_uri=None,\n                 debug=True,\n                 chip_size=300,\n                 chip_options=None):\n        super().__init__(rv.SEMANTIC_SEGMENTATION, predict_batch_size,\n                         predict_package_uri, debug)\n        self.class_map = class_map\n        self.chip_size = chip_size\n        if chip_options is None:\n            chip_options = SemanticSegmentationConfig.ChipOptions()\n        self.chip_options = chip_options\n\n    def save_bundle_files(self, bundle_dir):\n        return (self, [])\n\n    def load_bundle_files(self, bundle_dir):\n        return self\n\n    def create_task(self, backend):\n        return SemanticSegmentation(self, backend)\n\n    def to_proto(self):\n        msg = super().to_proto()\n        chip_options = TaskConfigMsg.SemanticSegmentationConfig.ChipOptions(\n            window_method=self.chip_options.window_method,\n            target_classes=self.chip_options.target_classes,\n            debug_chip_probability=self.chip_options.debug_chip_probability,\n            negative_survival_probability=self.chip_options.\n            negative_survival_probability,\n            chips_per_scene=self.chip_options.chips_per_scene,\n            target_count_threshold=self.chip_options.target_count_threshold,\n            stride=self.chip_options.stride)\n\n        conf = TaskConfigMsg.SemanticSegmentationConfig(\n            chip_size=self.chip_size,\n            class_items=self.class_map.to_proto(),\n            chip_options=chip_options)\n        msg.MergeFrom(\n            TaskConfigMsg(\n                semantic_segmentation_config=conf,\n                predict_package_uri=self.predict_package_uri))\n\n        return msg\n\n\nclass SemanticSegmentationConfigBuilder(TaskConfigBuilder):\n    def __init__(self, prev=None):\n        config = {}\n        if prev:\n            config = {\n                'predict_batch_size': prev.predict_batch_size,\n                'predict_package_uri': prev.predict_package_uri,\n                'debug': prev.debug,\n                'class_map': prev.class_map,\n                'chip_size': prev.chip_size,\n                'chip_options': prev.chip_options\n            }\n        super().__init__(SemanticSegmentationConfig, config)\n\n    def from_proto(self, msg):\n        conf = msg.semantic_segmentation_config\n\n        negative_survival_probability = conf.chip_options \\\n                                            .negative_survival_probability\n\n        stride = conf.chip_options.stride\n        if stride == 0:\n            stride = None\n\n        return self.with_classes(list(conf.class_items)) \\\n                .with_predict_batch_size(msg.predict_batch_size) \\\n                .with_predict_package_uri(msg.predict_package_uri) \\\n                .with_debug(msg.debug) \\\n                .with_chip_size(conf.chip_size) \\\n                .with_chip_options(\n                    window_method=conf.chip_options.window_method,\n                    target_classes=list(conf.chip_options.target_classes),\n                    debug_chip_probability=conf.chip_options.debug_chip_probability,\n                    negative_survival_probability=negative_survival_probability,\n                    chips_per_scene=conf.chip_options.chips_per_scene,\n                    target_count_threshold=conf.chip_options.target_count_threshold,\n                    stride=stride)\n\n    def validate(self):\n        super().validate()\n        # Segmentation masks are stored as uint8 to save space, so can only handle 256\n        # classes. If this is really needed, we can add an option for saving with uint16.\n        max_classes = 256\n        if len(self.config['class_map']) > max_classes:\n            raise rv.ConfigError(\n                'Cannot use more than {} classes with semantic segmentation.'.\n                format(max_classes))\n\n    def with_classes(\n            self, classes: Union[ClassMap, List[str], List[ClassItemMsg], List[\n                ClassItem], Dict[str, int], Dict[str, Tuple[int, str]]]):\n        \"\"\"Set the classes for this task.\n\n            Args:\n                classes: Either a list of class names, a dict which\n                         maps class names to class ids, or a dict\n                         which maps class names to a tuple of (class_id, color),\n                         where color is a PIL color string.\n        \"\"\"\n        b = deepcopy(self)\n        b.config['class_map'] = ClassMap.construct_from(classes)\n        return b\n\n    def with_chip_size(self, chip_size):\n        \"\"\"Set the chip_size for this task.\n\n            Args:\n                chip_size: Integer value chip size\n        \"\"\"\n        b = deepcopy(self)\n        b.config['chip_size'] = chip_size\n        return b\n\n    def with_chip_options(self,\n                          window_method='random_sample',\n                          target_classes=None,\n                          debug_chip_probability=0.25,\n                          negative_survival_probability=1.0,\n                          chips_per_scene=1000,\n                          target_count_threshold=1000,\n                          stride=None):\n        \"\"\"Sets semantic segmentation configurations for the Chip command\n\n           Args:\n            window_method: Window method to use for chipping.\n                           Options are: random_sample, sliding\n            target_classes: list of class ids to train model on\n            debug_chip_probability: probability of generating a debug chip.\n                                    Applies to the 'random_sample' window method.\n            negative_survival_probability: probability that a sampled negative\n                                           chip will be utilized if it does not\n                                           contain more pixels than\n                                           target_count_threshold.\n                                           Applies to the 'random_sample' window method.\n            chips_per_scene: number of chips to generate per scene.\n                             Applies to the 'random_sample' window method.\n            target_count_threshold: minimum number of pixels covering target_classes\n                                    that a chip must have.\n                                    Applies to the 'random_sample' window method.\n            stride: Stride of windows across image. Defaults to half the chip size.\n                    Applies to the 'sliding_window' method.\n\n        Returns:\n            SemanticSegmentationConfigBuilder\n        \"\"\"\n        b = deepcopy(self)\n\n        b.config['chip_options'] = SemanticSegmentationConfig.ChipOptions(\n            window_method=window_method,\n            target_classes=target_classes,\n            debug_chip_probability=debug_chip_probability,\n            negative_survival_probability=negative_survival_probability,\n            chips_per_scene=chips_per_scene,\n            target_count_threshold=target_count_threshold,\n            stride=stride)\n        return b\n", "path": "rastervision/task/semantic_segmentation_config.py"}, {"content": "from typing import List\nimport logging\n\nimport numpy as np\n\nfrom .task import Task\nfrom rastervision.core.box import Box\nfrom rastervision.data.scene import Scene\nfrom rastervision.data.label import SemanticSegmentationLabels\n\nlog = logging.getLogger(__name__)\n\n\ndef get_random_sample_train_windows(label_store, chip_size, class_map, extent,\n                                    chip_options, filter_windows):\n    prob = chip_options.negative_survival_probability\n    target_count_threshold = chip_options.target_count_threshold\n    target_classes = chip_options.target_classes\n    chips_per_scene = chip_options.chips_per_scene\n\n    if not target_classes:\n        all_class_ids = [item.id for item in class_map.get_items()]\n        target_classes = all_class_ids\n\n    windows = []\n    attempts = 0\n    while (attempts < chips_per_scene):\n        candidate_window = extent.make_random_square(chip_size)\n        if not filter_windows([candidate_window]):\n            continue\n        attempts = attempts + 1\n\n        if (prob >= 1.0):\n            windows.append(candidate_window)\n        elif attempts == chips_per_scene and len(windows) == 0:\n            windows.append(candidate_window)\n        else:\n            good = label_store.enough_target_pixels(\n                candidate_window, target_count_threshold, target_classes)\n            if good or (np.random.rand() < prob):\n                windows.append(candidate_window)\n\n    return windows\n\n\nclass SemanticSegmentation(Task):\n    \"\"\"Task-derived type that implements the semantic segmentation task.\"\"\"\n\n    def get_train_windows(self, scene: Scene) -> List[Box]:\n        \"\"\"Get training windows covering a scene.\n\n        Args:\n             scene: The scene over-which windows are to be generated.\n\n        Returns:\n             A list of windows, list(Box)\n\n        \"\"\"\n\n        def filter_windows(windows):\n            if scene.aoi_polygons:\n                windows = Box.filter_by_aoi(windows, scene.aoi_polygons)\n            return windows\n\n        raster_source = scene.raster_source\n        extent = raster_source.get_extent()\n        label_store = scene.ground_truth_label_source\n        chip_size = self.config.chip_size\n\n        chip_options = self.config.chip_options\n\n        if chip_options.window_method == 'random_sample':\n            return get_random_sample_train_windows(\n                label_store, chip_size, self.config.class_map, extent,\n                chip_options, filter_windows)\n        elif chip_options.window_method == 'sliding':\n            stride = chip_options.stride\n            if stride is None:\n                stride = chip_size / 2\n            stride = int(round(stride))\n\n            return list(\n                filter_windows((extent.get_windows(chip_size, stride))))\n\n    def get_train_labels(self, window: Box, scene: Scene) -> np.ndarray:\n        \"\"\"Get the training labels for the given window in the given scene.\n\n        Args:\n             window: The window over-which the labels are to be\n                  retrieved.\n             scene: The scene from-which the window of labels is to be\n                  extracted.\n\n        Returns:\n             An appropriately-shaped 2d np.ndarray with the labels\n             encoded as packed pixels.\n\n        \"\"\"\n        label_store = scene.ground_truth_label_source\n        return label_store.get_labels(window)\n\n    def get_predict_windows(self, extent: Box) -> List[Box]:\n        \"\"\"Get windows over-which predictions will be calculated.\n\n        Args:\n             extent: The overall extent of the area.\n\n        Returns:\n             An sequence of windows.\n\n        \"\"\"\n        chip_size = self.config.chip_size\n        return extent.get_windows(chip_size, chip_size)\n\n    def post_process_predictions(self, labels, scene):\n        return labels\n\n    def save_debug_predict_image(self, scene, debug_dir_uri):\n        # TODO implement this\n        pass\n\n    def predict_scene(self, scene, tmp_dir):\n        \"\"\"Predict on a single scene, and return the labels.\"\"\"\n        log.info('Making predictions for scene')\n        raster_source = scene.raster_source\n        windows = self.get_predict_windows(raster_source.get_extent())\n\n        def label_fn(window):\n            chip = raster_source.get_chip(window)\n            labels = self.backend.predict([chip], [window], tmp_dir)\n            label_arr = labels.get_label_arr(window)\n\n            # Set NODATA pixels in imagery to predicted value of 0 (ie. ignore)\n            label_arr[np.sum(chip, axis=2) == 0] = 0\n\n            print('.', end='', flush=True)\n            return label_arr\n\n        return SemanticSegmentationLabels(windows, label_fn)\n", "path": "rastervision/task/semantic_segmentation.py"}]}