prompt: You will be provided with a partial code base and an issue statement explaining a problem to resolve.
  <issue>
  _convert_to_cog function doesn't generate COG
  The current _convert_to_cog function (https://github.com/ResonantGeoData/ResonantGeoData/blob/master/rgd/geodata/models/imagery/subsample.py#L32-L51) doesn't output a COG; it just outputs a tiled tiff file.  GDAL has two separate format writers; one for regular TIFF and one for COG.  Without the '-of COG' option, the regular tiff writer is invoked.  The options available to the two writers differ as well: for COG you can specify a predictor with a string value, for regular tiff you must specify a numeric predictor value.
  
  Using lzw compression, I'd recommend the following options: `['-co', 'COMPRESS=LZW', '-co', 'PREDICTOR=YES', '-of', 'COG']`.  The default block (tile) size in the COG writer is 512 pixels; some tile servers or consumers seem to prefer 256; if so, add `-co BLOCKSIZE=256`.
  
  You can use tiffdump to see that COG files have multiple directories at different resolutions while non-COG files have a single directory.
  
  
  </issue>
  <code>
  [start of rgd/geodata/models/imagery/subsample.py]
  1 """Tasks for subsampling images with GDAL."""
  2 import os
  3 import tempfile
  4 
  5 from celery.utils.log import get_task_logger
  6 from django.conf import settings
  7 from girder_utils.files import field_file_to_local_path
  8 from osgeo import gdal
  9 
  10 from ..common import ArbitraryFile
  11 from .base import ConvertedImageFile
  12 
  13 logger = get_task_logger(__name__)
  14 
  15 
  16 def _gdal_translate(source_field, output_field, **kwargs):
  17     workdir = getattr(settings, 'GEODATA_WORKDIR', None)
  18     tmpdir = tempfile.mkdtemp(dir=workdir)
  19 
  20     with field_file_to_local_path(source_field) as file_path:
  21         logger.info(f'The image file path: {file_path}')
  22         output_path = os.path.join(tmpdir, 'subsampled_' + os.path.basename(file_path))
  23         ds = gdal.Open(str(file_path))
  24         ds = gdal.Translate(output_path, ds, **kwargs)
  25         ds = None
  26 
  27     output_field.save(os.path.basename(output_path), open(output_path, 'rb'))
  28 
  29     return
  30 
  31 
  32 def convert_to_cog(cog_id):
  33     """Populate ConvertedImageFile with COG file."""
  34     options = [
  35         '-co',
  36         'COMPRESS=LZW',
  37         '-co',
  38         'TILED=YES',
  39     ]
  40     cog = ConvertedImageFile.objects.get(id=cog_id)
  41     cog.converted_file = ArbitraryFile()
  42     src = cog.source_image.image_file.imagefile.file
  43     output = cog.converted_file.file
  44     _gdal_translate(src, output, options=options)
  45     cog.converted_file.save()
  46     cog.save(
  47         update_fields=[
  48             'converted_file',
  49         ]
  50     )
  51     return
  52
  [end of rgd/geodata/models/imagery/subsample.py]
  </code>
  
  I need you to solve this issue by generating a single patch file that I can apply directly to this repository using git apply. Please respond with a single patch file in the following format.
  <patch>
  diff --git a/file.py b/file.py
  --- a/file.py
  +++ b/file.py
  @@ -1,27 +1,35 @@
   def euclidean(a, b):
  -    while b:
  -        a, b = b, a % b
  -    return a
  +    if b == 0:
  +        return a
  +    return euclidean(b, a % b)
   
   
   def bresenham(x0, y0, x1, y1):
       points = []
       dx = abs(x1 - x0)
       dy = abs(y1 - y0)
  -    sx = 1 if x0 < x1 else -1
  -    sy = 1 if y0 < y1 else -1
  -    err = dx - dy
  +    x, y = x0, y0
  +    sx = -1 if x0 > x1 else 1
  +    sy = -1 if y0 > y1 else 1
   
  -    while True:
  -        points.append((x0, y0))
  -        if x0 == x1 and y0 == y1:
  -            break
  -        e2 = 2 * err
  -        if e2 > -dy:
  -            err -= dy
  -            x0 += sx
  -        if e2 < dx:
  -            err += dx
  -            y0 += sy
  +    if dx > dy:
  +        err = dx / 2.0
  +        while x != x1:
  +            points.append((x, y))
  +            err -= dy
  +            if err < 0:
  +                y += sy
  +                err += dx
  +            x += sx
  +    else:
  +        err = dy / 2.0
  +        while y != y1:
  +            points.append((x, y))
  +            err -= dx
  +            if err < 0:
  +                x += sx
  +                err += dy
  +            y += sy
  +
  +    points.append((x, y))
       return points
  
  </patch>
golden_diff: diff --git a/rgd/geodata/models/imagery/subsample.py b/rgd/geodata/models/imagery/subsample.py
  --- a/rgd/geodata/models/imagery/subsample.py
  +++ b/rgd/geodata/models/imagery/subsample.py
  @@ -35,7 +35,11 @@
           '-co',
           'COMPRESS=LZW',
           '-co',
  -        'TILED=YES',
  +        'PREDICTOR=YES',
  +        '-of',
  +        'COG',
  +        '-co',
  +        'BLOCKSIZE=256',
       ]
       cog = ConvertedImageFile.objects.get(id=cog_id)
       cog.converted_file = ArbitraryFile()
  
verification_info: {"golden_diff": "diff --git a/rgd/geodata/models/imagery/subsample.py b/rgd/geodata/models/imagery/subsample.py\n--- a/rgd/geodata/models/imagery/subsample.py\n+++ b/rgd/geodata/models/imagery/subsample.py\n@@ -35,7 +35,11 @@\n         '-co',\n         'COMPRESS=LZW',\n         '-co',\n-        'TILED=YES',\n+        'PREDICTOR=YES',\n+        '-of',\n+        'COG',\n+        '-co',\n+        'BLOCKSIZE=256',\n     ]\n     cog = ConvertedImageFile.objects.get(id=cog_id)\n     cog.converted_file = ArbitraryFile()\n", "issue": "_convert_to_cog function doesn't generate COG\nThe current _convert_to_cog function (https://github.com/ResonantGeoData/ResonantGeoData/blob/master/rgd/geodata/models/imagery/subsample.py#L32-L51) doesn't output a COG; it just outputs a tiled tiff file.  GDAL has two separate format writers; one for regular TIFF and one for COG.  Without the '-of COG' option, the regular tiff writer is invoked.  The options available to the two writers differ as well: for COG you can specify a predictor with a string value, for regular tiff you must specify a numeric predictor value.\r\n\r\nUsing lzw compression, I'd recommend the following options: `['-co', 'COMPRESS=LZW', '-co', 'PREDICTOR=YES', '-of', 'COG']`.  The default block (tile) size in the COG writer is 512 pixels; some tile servers or consumers seem to prefer 256; if so, add `-co BLOCKSIZE=256`.\r\n\r\nYou can use tiffdump to see that COG files have multiple directories at different resolutions while non-COG files have a single directory.\r\n\n", "before_files": [{"content": "\"\"\"Tasks for subsampling images with GDAL.\"\"\"\nimport os\nimport tempfile\n\nfrom celery.utils.log import get_task_logger\nfrom django.conf import settings\nfrom girder_utils.files import field_file_to_local_path\nfrom osgeo import gdal\n\nfrom ..common import ArbitraryFile\nfrom .base import ConvertedImageFile\n\nlogger = get_task_logger(__name__)\n\n\ndef _gdal_translate(source_field, output_field, **kwargs):\n    workdir = getattr(settings, 'GEODATA_WORKDIR', None)\n    tmpdir = tempfile.mkdtemp(dir=workdir)\n\n    with field_file_to_local_path(source_field) as file_path:\n        logger.info(f'The image file path: {file_path}')\n        output_path = os.path.join(tmpdir, 'subsampled_' + os.path.basename(file_path))\n        ds = gdal.Open(str(file_path))\n        ds = gdal.Translate(output_path, ds, **kwargs)\n        ds = None\n\n    output_field.save(os.path.basename(output_path), open(output_path, 'rb'))\n\n    return\n\n\ndef convert_to_cog(cog_id):\n    \"\"\"Populate ConvertedImageFile with COG file.\"\"\"\n    options = [\n        '-co',\n        'COMPRESS=LZW',\n        '-co',\n        'TILED=YES',\n    ]\n    cog = ConvertedImageFile.objects.get(id=cog_id)\n    cog.converted_file = ArbitraryFile()\n    src = cog.source_image.image_file.imagefile.file\n    output = cog.converted_file.file\n    _gdal_translate(src, output, options=options)\n    cog.converted_file.save()\n    cog.save(\n        update_fields=[\n            'converted_file',\n        ]\n    )\n    return\n", "path": "rgd/geodata/models/imagery/subsample.py"}]}