We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Allow Map Tiles to be evaluated
I am trying to make rastervision work for a tiled map, so I run it on each tile I have, for example:
![image](https://user-images.githubusercontent.com/5757359/55006587-a45ad780-4fe6-11e9-8f6c-86e2ffedc23d.png)

When I do, I get the error:

> rastervision_1  | Executing rastervision predict /app/packages/xView_Vehicle.zip /images/674915186.png output/xView_Vehicle_674915186.png.json
> rastervision_1  | (node:7) UnhandledPromiseRejectionWarning: Error: Command failed: rastervision predict /app/packages/xView_Vehicle.zip /images/674915186.png output/xView_Vehicle_674915186.png.json
> rastervision_1  | 2019-03-26 14:44:13.975033: I tensorflow/core/platform/cpu_feature_guard.cc:141] Your CPU supports instructions that this TensorFlow binary was not compiled to use: AVX2 FMA
> rastervision_1  | /usr/local/lib/python3.5/dist-packages/pluginbase.py:439: FutureWarning: Conversion of the second argument of issubdtype from `float` to `np.floating` is deprecated. In future, it will be treated as `np.float64 == np.dtype(float).type`.
> rastervision_1  |   fromlist, level)
> rastervision_1  | /usr/local/lib/python3.5/dist-packages/rasterio/__init__.py:217: NotGeoreferencedWarning: Dataset has no geotransform set. The identity matrix may be returned.
> rastervision_1  |   s = DatasetReader(path, driver=driver, **kwargs)
> rastervision_1  | 2019-03-26 14:44:13:rastervision.task.task: INFO - Making predictions for scene
> rastervision_1  | Traceback (most recent call last):
> rastervision_1  |   File "/usr/lib/python3.5/runpy.py", line 184, in _run_module_as_main
> rastervision_1  |     "__main__", mod_spec)
> rastervision_1  |   File "/usr/lib/python3.5/runpy.py", line 85, in _run_code
> rastervision_1  |     exec(code, run_globals)
> rastervision_1  |   File "/opt/src/rastervision/__main__.py", line 17, in <module>
> rastervision_1  |     rv.main()
> rastervision_1  |   File "/usr/local/lib/python3.5/dist-packages/click/core.py", line 722, in __call__
> rastervision_1  |     return self.main(*args, **kwargs)
> rastervision_1  |   File "/usr/local/lib/python3.5/dist-packages/click/core.py", line 697, in main
> rastervision_1  |     rv = self.invoke(ctx)
> rastervision_1  |   File "/usr/local/lib/python3.5/dist-packages/click/core.py", line 1066, in invoke
> rastervision_1  |     return _process_result(sub_ctx.command.invoke(sub_ctx))
> rastervision_1  |   File "/usr/local/lib/python3.5/dist-packages/click/core.py", line 895, in invoke
> rastervision_1  |     return ctx.invoke(self.callback, **ctx.params)
> rastervision_1  |   File "/usr/local/lib/python3.5/dist-packages/click/core.py", line 535, in invoke
> rastervision_1  |     return callback(*args, **kwargs)
> rastervision_1  |   File "/opt/src/rastervision/cli/main.py", line 240, in predict
> rastervision_1  |     predictor.predict(image_uri, output_uri, export_config)
> rastervision_1  |   File "/opt/src/rastervision/predictor.py", line 142, in predict
> rastervision_1  |     labels = self.task.predict_scene(scene, self.tmp_dir)
> rastervision_1  |   File "/opt/src/rastervision/task/task.py", line 192, in predict_scene
> rastervision_1  |     predict_batch(batch_chips, batch_windows)
> rastervision_1  |   File "/opt/src/rastervision/task/task.py", line 173, in predict_batch
> rastervision_1  |     np.array(predict_chips), predict_windows, tmp_dir)
> rastervision_1  |   File "/opt/src/rastervision/backend/tf_object_detection.py", line 736, in predict
> rastervision_1  |     self.session)
> rastervision_1  |   File "/opt/src/rastervision/backend/tf_object_detection.py", line 573, in compute_prediction
> rastervision_1  |     [boxes, scores, class_ids], feed_dict={image_tensor: image_nps})
> rastervision_1  |   File "/usr/local/lib/python3.5/dist-packages/tensorflow/python/client/session.py", line 877, in run
> rastervision_1  |     run_metadata_ptr)
> rastervision_1  |   File "/usr/local/lib/python3.5/dist-packages/tensorflow/python/client/session.py", line 1076, in _run
> rastervision_1  |     str(subfeed_t.get_shape())))
> rastervision_1  | ValueError: Cannot feed value of shape (2, 300, 300, 1) for Tensor 'image_tensor:0', which has shape '(?, ?, ?, 3)'
> rastervision_1  | 
> rastervision_1  |     at ChildProcess.exithandler (child_process.js:294:12)
> rastervision_1  |     at ChildProcess.emit (events.js:189:13)
> rastervision_1  |     at maybeClose (internal/child_process.js:970:16)
> rastervision_1  |     at Process.ChildProcess._handle.onexit (internal/child_process.js:259:5)
> rastervision_1  | (node:7) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 1)
> rastervision_1  | (node:7) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.

I am successfull at running the same code on TIF files, and JPEG.

--- 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/data/raster_source/raster_source_config.py`
Content:
```
1 from abc import abstractmethod
2 from copy import deepcopy
3 import logging
4 
5 import rastervision as rv
6 from rastervision.core.config import (Config, ConfigBuilder,
7                                       BundledConfigMixin)
8 from rastervision.data import (RasterTransformerConfig, StatsTransformerConfig)
9 from rastervision.protos.raster_source_pb2 \
10     import RasterSourceConfig as RasterSourceConfigMsg
11 
12 log = logging.getLogger(__name__)
13 
14 
15 class RasterSourceConfig(BundledConfigMixin, Config):
16     deprecation_warnings = []
17 
18     def __init__(self, source_type, transformers=None, channel_order=None):
19         if transformers is None:
20             transformers = []
21 
22         self.source_type = source_type
23         self.transformers = transformers
24         self.channel_order = channel_order
25 
26     def to_proto(self):
27         transformers = list(map(lambda c: c.to_proto(), self.transformers))
28         msg = RasterSourceConfigMsg(
29             source_type=self.source_type,
30             channel_order=self.channel_order,
31             transformers=transformers)
32         return msg
33 
34     def save_bundle_files(self, bundle_dir):
35         new_transformers = []
36         files = []
37         for transformer in self.transformers:
38             new_transformer, t_files = transformer.save_bundle_files(
39                 bundle_dir)
40             new_transformers.append(new_transformer)
41             files.extend(t_files)
42 
43         new_config = self.to_builder() \
44                          .with_transformers(new_transformers) \
45                          .build()
46         return (new_config, files)
47 
48     def load_bundle_files(self, bundle_dir):
49         new_transformers = []
50         for transformer in self.transformers:
51             new_transformer = transformer.load_bundle_files(bundle_dir)
52             new_transformers.append(new_transformer)
53         return self.to_builder() \
54                    .with_transformers(new_transformers) \
55                    .build()
56 
57     @abstractmethod
58     def create_source(self, tmp_dir, crs_transformer, extent, class_map):
59         """Create the Raster Source for this configuration.
60         """
61         pass
62 
63     def to_builder(self):
64         return rv._registry.get_config_builder(rv.RASTER_SOURCE,
65                                                self.source_type)(self)
66 
67     @staticmethod
68     def check_deprecation(source_type):
69         # If source_type is deprecated and warning hasn't been shown yet, then warn.
70         if (source_type in rv.raster_source_deprecated_map and
71                 source_type not in RasterSourceConfig.deprecation_warnings):
72             RasterSourceConfig.deprecation_warnings.append(source_type)
73             new_source_type = rv.raster_source_deprecated_map[source_type]
74             log.warn(
75                 'RasterSource {} is deprecated. Please use {} instead.'.format(
76                     source_type, new_source_type))
77 
78     def builder(source_type):
79         RasterSourceConfig.check_deprecation(source_type)
80         return rv._registry.get_config_builder(rv.RASTER_SOURCE, source_type)()
81 
82     @staticmethod
83     def from_proto(msg):
84         """Creates a TaskConfig from the specificed protobuf message
85         """
86         return rv._registry.get_config_builder(rv.RASTER_SOURCE, msg.source_type)() \
87                            .from_proto(msg) \
88                            .build()
89 
90     @abstractmethod
91     def for_prediction(self, image_uri):
92         """Creates a new config with the image_uri."""
93         pass
94 
95     @abstractmethod
96     def create_local(self, tmp_dir):
97         """Returns a new config with a local copy of the image data
98         if this image is remote.
99         """
100         pass
101 
102     def create_transformers(self):
103         return list(map(lambda c: c.create_transformer(), self.transformers))
104 
105     def update_for_command(self, command_type, experiment_config,
106                            context=None):
107         for transformer in self.transformers:
108             transformer.update_for_command(command_type, experiment_config,
109                                            context)
110 
111     def report_io(self, command_type, io_def):
112         for transformer in self.transformers:
113             transformer.report_io(command_type, io_def)
114 
115 
116 class RasterSourceConfigBuilder(ConfigBuilder):
117     def from_proto(self, msg):
118         transformers = list(
119             map(lambda m: RasterTransformerConfig.from_proto(m),
120                 msg.transformers))
121 
122         return self.with_channel_order(list(msg.channel_order)) \
123                    .with_transformers(transformers)
124 
125     def with_channel_order(self, channel_order):
126         """Defines the channel order for this raster source.
127 
128         This defines the subset of channel indices and their order to use when extracting
129         chips from raw imagery.
130 
131         Args:
132             channel_order: list of channel indices
133         """
134         b = deepcopy(self)
135         b.config['channel_order'] = channel_order
136         return b
137 
138     def with_transformers(self, transformers):
139         """Transformers to be applied to the raster data.
140 
141             Args:
142                 transformers: A list of transformers to apply to the
143                     raster data.
144 
145         """
146         b = deepcopy(self)
147         b.config['transformers'] = list(transformers)
148         return b
149 
150     def with_transformer(self, transformer):
151         """A transformer to be applied to the raster data.
152 
153             Args:
154                 transformer: A transformer to apply to the raster
155                     data.
156 
157         """
158         return self.with_transformers([transformer])
159 
160     def with_stats_transformer(self):
161         """Add a stats transformer to the raster source."""
162         b = deepcopy(self)
163         transformers = b.config.get('transformers')
164         if transformers:
165             b.config['transformers'] = transformers.append(
166                 StatsTransformerConfig())
167         else:
168             b.config['transformers'] = [StatsTransformerConfig()]
169         return b
170
```
--- 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/data/raster_source/raster_source_config.py b/rastervision/data/raster_source/raster_source_config.py
--- a/rastervision/data/raster_source/raster_source_config.py
+++ b/rastervision/data/raster_source/raster_source_config.py
@@ -119,7 +119,10 @@
             map(lambda m: RasterTransformerConfig.from_proto(m),
                 msg.transformers))
 
-        return self.with_channel_order(list(msg.channel_order)) \
+        channel_order = list(msg.channel_order)
+        if len(channel_order) == 0:
+            channel_order = None
+        return self.with_channel_order(channel_order) \
                    .with_transformers(transformers)
 
     def with_channel_order(self, channel_order):

{"golden_diff": "diff --git a/rastervision/data/raster_source/raster_source_config.py b/rastervision/data/raster_source/raster_source_config.py\n--- a/rastervision/data/raster_source/raster_source_config.py\n+++ b/rastervision/data/raster_source/raster_source_config.py\n@@ -119,7 +119,10 @@\n             map(lambda m: RasterTransformerConfig.from_proto(m),\n                 msg.transformers))\n \n-        return self.with_channel_order(list(msg.channel_order)) \\\n+        channel_order = list(msg.channel_order)\n+        if len(channel_order) == 0:\n+            channel_order = None\n+        return self.with_channel_order(channel_order) \\\n                    .with_transformers(transformers)\n \n     def with_channel_order(self, channel_order):\n", "issue": "Allow Map Tiles to be evaluated\nI am trying to make rastervision work for a tiled map, so I run it on each tile I have, for example:\r\n![image](https://user-images.githubusercontent.com/5757359/55006587-a45ad780-4fe6-11e9-8f6c-86e2ffedc23d.png)\r\n\r\nWhen I do, I get the error:\r\n\r\n> rastervision_1  | Executing rastervision predict /app/packages/xView_Vehicle.zip /images/674915186.png output/xView_Vehicle_674915186.png.json\r\n> rastervision_1  | (node:7) UnhandledPromiseRejectionWarning: Error: Command failed: rastervision predict /app/packages/xView_Vehicle.zip /images/674915186.png output/xView_Vehicle_674915186.png.json\r\n> rastervision_1  | 2019-03-26 14:44:13.975033: I tensorflow/core/platform/cpu_feature_guard.cc:141] Your CPU supports instructions that this TensorFlow binary was not compiled to use: AVX2 FMA\r\n> rastervision_1  | /usr/local/lib/python3.5/dist-packages/pluginbase.py:439: FutureWarning: Conversion of the second argument of issubdtype from `float` to `np.floating` is deprecated. In future, it will be treated as `np.float64 == np.dtype(float).type`.\r\n> rastervision_1  |   fromlist, level)\r\n> rastervision_1  | /usr/local/lib/python3.5/dist-packages/rasterio/__init__.py:217: NotGeoreferencedWarning: Dataset has no geotransform set. The identity matrix may be returned.\r\n> rastervision_1  |   s = DatasetReader(path, driver=driver, **kwargs)\r\n> rastervision_1  | 2019-03-26 14:44:13:rastervision.task.task: INFO - Making predictions for scene\r\n> rastervision_1  | Traceback (most recent call last):\r\n> rastervision_1  |   File \"/usr/lib/python3.5/runpy.py\", line 184, in _run_module_as_main\r\n> rastervision_1  |     \"__main__\", mod_spec)\r\n> rastervision_1  |   File \"/usr/lib/python3.5/runpy.py\", line 85, in _run_code\r\n> rastervision_1  |     exec(code, run_globals)\r\n> rastervision_1  |   File \"/opt/src/rastervision/__main__.py\", line 17, in <module>\r\n> rastervision_1  |     rv.main()\r\n> rastervision_1  |   File \"/usr/local/lib/python3.5/dist-packages/click/core.py\", line 722, in __call__\r\n> rastervision_1  |     return self.main(*args, **kwargs)\r\n> rastervision_1  |   File \"/usr/local/lib/python3.5/dist-packages/click/core.py\", line 697, in main\r\n> rastervision_1  |     rv = self.invoke(ctx)\r\n> rastervision_1  |   File \"/usr/local/lib/python3.5/dist-packages/click/core.py\", line 1066, in invoke\r\n> rastervision_1  |     return _process_result(sub_ctx.command.invoke(sub_ctx))\r\n> rastervision_1  |   File \"/usr/local/lib/python3.5/dist-packages/click/core.py\", line 895, in invoke\r\n> rastervision_1  |     return ctx.invoke(self.callback, **ctx.params)\r\n> rastervision_1  |   File \"/usr/local/lib/python3.5/dist-packages/click/core.py\", line 535, in invoke\r\n> rastervision_1  |     return callback(*args, **kwargs)\r\n> rastervision_1  |   File \"/opt/src/rastervision/cli/main.py\", line 240, in predict\r\n> rastervision_1  |     predictor.predict(image_uri, output_uri, export_config)\r\n> rastervision_1  |   File \"/opt/src/rastervision/predictor.py\", line 142, in predict\r\n> rastervision_1  |     labels = self.task.predict_scene(scene, self.tmp_dir)\r\n> rastervision_1  |   File \"/opt/src/rastervision/task/task.py\", line 192, in predict_scene\r\n> rastervision_1  |     predict_batch(batch_chips, batch_windows)\r\n> rastervision_1  |   File \"/opt/src/rastervision/task/task.py\", line 173, in predict_batch\r\n> rastervision_1  |     np.array(predict_chips), predict_windows, tmp_dir)\r\n> rastervision_1  |   File \"/opt/src/rastervision/backend/tf_object_detection.py\", line 736, in predict\r\n> rastervision_1  |     self.session)\r\n> rastervision_1  |   File \"/opt/src/rastervision/backend/tf_object_detection.py\", line 573, in compute_prediction\r\n> rastervision_1  |     [boxes, scores, class_ids], feed_dict={image_tensor: image_nps})\r\n> rastervision_1  |   File \"/usr/local/lib/python3.5/dist-packages/tensorflow/python/client/session.py\", line 877, in run\r\n> rastervision_1  |     run_metadata_ptr)\r\n> rastervision_1  |   File \"/usr/local/lib/python3.5/dist-packages/tensorflow/python/client/session.py\", line 1076, in _run\r\n> rastervision_1  |     str(subfeed_t.get_shape())))\r\n> rastervision_1  | ValueError: Cannot feed value of shape (2, 300, 300, 1) for Tensor 'image_tensor:0', which has shape '(?, ?, ?, 3)'\r\n> rastervision_1  | \r\n> rastervision_1  |     at ChildProcess.exithandler (child_process.js:294:12)\r\n> rastervision_1  |     at ChildProcess.emit (events.js:189:13)\r\n> rastervision_1  |     at maybeClose (internal/child_process.js:970:16)\r\n> rastervision_1  |     at Process.ChildProcess._handle.onexit (internal/child_process.js:259:5)\r\n> rastervision_1  | (node:7) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 1)\r\n> rastervision_1  | (node:7) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.\r\n\r\nI am successfull at running the same code on TIF files, and JPEG.\n", "before_files": [{"content": "from abc import abstractmethod\nfrom copy import deepcopy\nimport logging\n\nimport rastervision as rv\nfrom rastervision.core.config import (Config, ConfigBuilder,\n                                      BundledConfigMixin)\nfrom rastervision.data import (RasterTransformerConfig, StatsTransformerConfig)\nfrom rastervision.protos.raster_source_pb2 \\\n    import RasterSourceConfig as RasterSourceConfigMsg\n\nlog = logging.getLogger(__name__)\n\n\nclass RasterSourceConfig(BundledConfigMixin, Config):\n    deprecation_warnings = []\n\n    def __init__(self, source_type, transformers=None, channel_order=None):\n        if transformers is None:\n            transformers = []\n\n        self.source_type = source_type\n        self.transformers = transformers\n        self.channel_order = channel_order\n\n    def to_proto(self):\n        transformers = list(map(lambda c: c.to_proto(), self.transformers))\n        msg = RasterSourceConfigMsg(\n            source_type=self.source_type,\n            channel_order=self.channel_order,\n            transformers=transformers)\n        return msg\n\n    def save_bundle_files(self, bundle_dir):\n        new_transformers = []\n        files = []\n        for transformer in self.transformers:\n            new_transformer, t_files = transformer.save_bundle_files(\n                bundle_dir)\n            new_transformers.append(new_transformer)\n            files.extend(t_files)\n\n        new_config = self.to_builder() \\\n                         .with_transformers(new_transformers) \\\n                         .build()\n        return (new_config, files)\n\n    def load_bundle_files(self, bundle_dir):\n        new_transformers = []\n        for transformer in self.transformers:\n            new_transformer = transformer.load_bundle_files(bundle_dir)\n            new_transformers.append(new_transformer)\n        return self.to_builder() \\\n                   .with_transformers(new_transformers) \\\n                   .build()\n\n    @abstractmethod\n    def create_source(self, tmp_dir, crs_transformer, extent, class_map):\n        \"\"\"Create the Raster Source for this configuration.\n        \"\"\"\n        pass\n\n    def to_builder(self):\n        return rv._registry.get_config_builder(rv.RASTER_SOURCE,\n                                               self.source_type)(self)\n\n    @staticmethod\n    def check_deprecation(source_type):\n        # If source_type is deprecated and warning hasn't been shown yet, then warn.\n        if (source_type in rv.raster_source_deprecated_map and\n                source_type not in RasterSourceConfig.deprecation_warnings):\n            RasterSourceConfig.deprecation_warnings.append(source_type)\n            new_source_type = rv.raster_source_deprecated_map[source_type]\n            log.warn(\n                'RasterSource {} is deprecated. Please use {} instead.'.format(\n                    source_type, new_source_type))\n\n    def builder(source_type):\n        RasterSourceConfig.check_deprecation(source_type)\n        return rv._registry.get_config_builder(rv.RASTER_SOURCE, source_type)()\n\n    @staticmethod\n    def from_proto(msg):\n        \"\"\"Creates a TaskConfig from the specificed protobuf message\n        \"\"\"\n        return rv._registry.get_config_builder(rv.RASTER_SOURCE, msg.source_type)() \\\n                           .from_proto(msg) \\\n                           .build()\n\n    @abstractmethod\n    def for_prediction(self, image_uri):\n        \"\"\"Creates a new config with the image_uri.\"\"\"\n        pass\n\n    @abstractmethod\n    def create_local(self, tmp_dir):\n        \"\"\"Returns a new config with a local copy of the image data\n        if this image is remote.\n        \"\"\"\n        pass\n\n    def create_transformers(self):\n        return list(map(lambda c: c.create_transformer(), self.transformers))\n\n    def update_for_command(self, command_type, experiment_config,\n                           context=None):\n        for transformer in self.transformers:\n            transformer.update_for_command(command_type, experiment_config,\n                                           context)\n\n    def report_io(self, command_type, io_def):\n        for transformer in self.transformers:\n            transformer.report_io(command_type, io_def)\n\n\nclass RasterSourceConfigBuilder(ConfigBuilder):\n    def from_proto(self, msg):\n        transformers = list(\n            map(lambda m: RasterTransformerConfig.from_proto(m),\n                msg.transformers))\n\n        return self.with_channel_order(list(msg.channel_order)) \\\n                   .with_transformers(transformers)\n\n    def with_channel_order(self, channel_order):\n        \"\"\"Defines the channel order for this raster source.\n\n        This defines the subset of channel indices and their order to use when extracting\n        chips from raw imagery.\n\n        Args:\n            channel_order: list of channel indices\n        \"\"\"\n        b = deepcopy(self)\n        b.config['channel_order'] = channel_order\n        return b\n\n    def with_transformers(self, transformers):\n        \"\"\"Transformers to be applied to the raster data.\n\n            Args:\n                transformers: A list of transformers to apply to the\n                    raster data.\n\n        \"\"\"\n        b = deepcopy(self)\n        b.config['transformers'] = list(transformers)\n        return b\n\n    def with_transformer(self, transformer):\n        \"\"\"A transformer to be applied to the raster data.\n\n            Args:\n                transformer: A transformer to apply to the raster\n                    data.\n\n        \"\"\"\n        return self.with_transformers([transformer])\n\n    def with_stats_transformer(self):\n        \"\"\"Add a stats transformer to the raster source.\"\"\"\n        b = deepcopy(self)\n        transformers = b.config.get('transformers')\n        if transformers:\n            b.config['transformers'] = transformers.append(\n                StatsTransformerConfig())\n        else:\n            b.config['transformers'] = [StatsTransformerConfig()]\n        return b\n", "path": "rastervision/data/raster_source/raster_source_config.py"}], "after_files": [{"content": "from abc import abstractmethod\nfrom copy import deepcopy\nimport logging\n\nimport rastervision as rv\nfrom rastervision.core.config import (Config, ConfigBuilder,\n                                      BundledConfigMixin)\nfrom rastervision.data import (RasterTransformerConfig, StatsTransformerConfig)\nfrom rastervision.protos.raster_source_pb2 \\\n    import RasterSourceConfig as RasterSourceConfigMsg\n\nlog = logging.getLogger(__name__)\n\n\nclass RasterSourceConfig(BundledConfigMixin, Config):\n    deprecation_warnings = []\n\n    def __init__(self, source_type, transformers=None, channel_order=None):\n        if transformers is None:\n            transformers = []\n\n        self.source_type = source_type\n        self.transformers = transformers\n        self.channel_order = channel_order\n\n    def to_proto(self):\n        transformers = list(map(lambda c: c.to_proto(), self.transformers))\n        msg = RasterSourceConfigMsg(\n            source_type=self.source_type,\n            channel_order=self.channel_order,\n            transformers=transformers)\n        return msg\n\n    def save_bundle_files(self, bundle_dir):\n        new_transformers = []\n        files = []\n        for transformer in self.transformers:\n            new_transformer, t_files = transformer.save_bundle_files(\n                bundle_dir)\n            new_transformers.append(new_transformer)\n            files.extend(t_files)\n\n        new_config = self.to_builder() \\\n                         .with_transformers(new_transformers) \\\n                         .build()\n        return (new_config, files)\n\n    def load_bundle_files(self, bundle_dir):\n        new_transformers = []\n        for transformer in self.transformers:\n            new_transformer = transformer.load_bundle_files(bundle_dir)\n            new_transformers.append(new_transformer)\n        return self.to_builder() \\\n                   .with_transformers(new_transformers) \\\n                   .build()\n\n    @abstractmethod\n    def create_source(self, tmp_dir, crs_transformer, extent, class_map):\n        \"\"\"Create the Raster Source for this configuration.\n        \"\"\"\n        pass\n\n    def to_builder(self):\n        return rv._registry.get_config_builder(rv.RASTER_SOURCE,\n                                               self.source_type)(self)\n\n    @staticmethod\n    def check_deprecation(source_type):\n        # If source_type is deprecated and warning hasn't been shown yet, then warn.\n        if (source_type in rv.raster_source_deprecated_map and\n                source_type not in RasterSourceConfig.deprecation_warnings):\n            RasterSourceConfig.deprecation_warnings.append(source_type)\n            new_source_type = rv.raster_source_deprecated_map[source_type]\n            log.warn(\n                'RasterSource {} is deprecated. Please use {} instead.'.format(\n                    source_type, new_source_type))\n\n    def builder(source_type):\n        RasterSourceConfig.check_deprecation(source_type)\n        return rv._registry.get_config_builder(rv.RASTER_SOURCE, source_type)()\n\n    @staticmethod\n    def from_proto(msg):\n        \"\"\"Creates a TaskConfig from the specificed protobuf message\n        \"\"\"\n        return rv._registry.get_config_builder(rv.RASTER_SOURCE, msg.source_type)() \\\n                           .from_proto(msg) \\\n                           .build()\n\n    @abstractmethod\n    def for_prediction(self, image_uri):\n        \"\"\"Creates a new config with the image_uri.\"\"\"\n        pass\n\n    @abstractmethod\n    def create_local(self, tmp_dir):\n        \"\"\"Returns a new config with a local copy of the image data\n        if this image is remote.\n        \"\"\"\n        pass\n\n    def create_transformers(self):\n        return list(map(lambda c: c.create_transformer(), self.transformers))\n\n    def update_for_command(self, command_type, experiment_config,\n                           context=None):\n        for transformer in self.transformers:\n            transformer.update_for_command(command_type, experiment_config,\n                                           context)\n\n    def report_io(self, command_type, io_def):\n        for transformer in self.transformers:\n            transformer.report_io(command_type, io_def)\n\n\nclass RasterSourceConfigBuilder(ConfigBuilder):\n    def from_proto(self, msg):\n        transformers = list(\n            map(lambda m: RasterTransformerConfig.from_proto(m),\n                msg.transformers))\n\n        channel_order = list(msg.channel_order)\n        if len(channel_order) == 0:\n            channel_order = None\n        return self.with_channel_order(channel_order) \\\n                   .with_transformers(transformers)\n\n    def with_channel_order(self, channel_order):\n        \"\"\"Defines the channel order for this raster source.\n\n        This defines the subset of channel indices and their order to use when extracting\n        chips from raw imagery.\n\n        Args:\n            channel_order: list of channel indices\n        \"\"\"\n        b = deepcopy(self)\n        b.config['channel_order'] = channel_order\n        return b\n\n    def with_transformers(self, transformers):\n        \"\"\"Transformers to be applied to the raster data.\n\n            Args:\n                transformers: A list of transformers to apply to the\n                    raster data.\n\n        \"\"\"\n        b = deepcopy(self)\n        b.config['transformers'] = list(transformers)\n        return b\n\n    def with_transformer(self, transformer):\n        \"\"\"A transformer to be applied to the raster data.\n\n            Args:\n                transformer: A transformer to apply to the raster\n                    data.\n\n        \"\"\"\n        return self.with_transformers([transformer])\n\n    def with_stats_transformer(self):\n        \"\"\"Add a stats transformer to the raster source.\"\"\"\n        b = deepcopy(self)\n        transformers = b.config.get('transformers')\n        if transformers:\n            b.config['transformers'] = transformers.append(\n                StatsTransformerConfig())\n        else:\n            b.config['transformers'] = [StatsTransformerConfig()]\n        return b\n", "path": "rastervision/data/raster_source/raster_source_config.py"}]}