prompt: You will be provided with a partial code base and an issue statement explaining a problem to resolve.
  <issue>
  from_Cary handle duplicate named data
  Currently it will fail to read in data that has the same column header
  
  </issue>
  <code>
  [start of WrightTools/collection/_cary.py]
  1 """Cary."""
  2 
  3 
  4 # --- import --------------------------------------------------------------------------------------
  5 
  6 
  7 import os
  8 import re
  9 
  10 import numpy as np
  11 
  12 from .. import exceptions as wt_exceptions
  13 from ._collection import Collection
  14 
  15 
  16 # --- define --------------------------------------------------------------------------------------
  17 
  18 
  19 __all__ = ["from_Cary"]
  20 
  21 
  22 # --- from function -------------------------------------------------------------------------------
  23 
  24 
  25 def from_Cary(filepath, name=None, parent=None, verbose=True):
  26     """Create a collection object from a Cary UV VIS absorbance file.
  27 
  28     We hope to support as many Cary instruments and datasets as possible.
  29     This function has been tested with data collected on a Cary50 UV/VIS spectrometer.
  30     If any alternate instruments are found not to work as expected, please
  31     submit a bug report on our `issue tracker`__.
  32 
  33     __ github.com/wright-group/WrightTools/issues
  34 
  35     .. plot::
  36 
  37         >>> import WrightTools as wt
  38         >>> from WrightTools import datasets
  39         >>> p = datasets.Cary.CuPCtS_H2O_vis
  40         >>> data = wt.collection.from_Cary(p)[0]
  41         >>> wt.artists.quick1D(data)
  42 
  43     Parameters
  44     ----------
  45     filepath : string
  46         Path to Cary output file (.csv).
  47     parent : WrightTools.Collection
  48         A collection object in which to place a collection of Data objects.
  49     verbose : boolean (optional)
  50         Toggle talkback. Default is True.
  51 
  52     Returns
  53     -------
  54     data
  55         New data object.
  56     """
  57     # check filepath
  58     filesuffix = os.path.basename(filepath).split(".")[-1]
  59     if filesuffix != "csv":
  60         wt_exceptions.WrongFileTypeWarning.warn(filepath, "csv")
  61     if name is None:
  62         name = "cary"
  63     # import array
  64     lines = []
  65     with open(filepath, "r", encoding="iso-8859-1") as f:
  66         header = f.readline()
  67         columns = f.readline()
  68         while True:
  69             line = f.readline()
  70             if line == "\n" or line == "":
  71                 break
  72             else:
  73                 # Note, it is necessary to call this twice, as a single call will
  74                 # result in something like ',,,,' > ',nan,,nan,'.
  75                 line = line.replace(",,", ",nan,")
  76                 line = line.replace(",,", ",nan,")
  77                 # Ensure that the first column has nan, if necessary
  78                 if line[0] == ",":
  79                     line = "nan" + line
  80                 clean = line[:-2]  # lines end with ',/n'
  81                 lines.append(np.fromstring(clean, sep=","))
  82     lines = [line for line in lines if len(line) > 0]
  83     header = header.split(",")
  84     columns = columns.split(",")
  85     arr = np.array(lines).T
  86     # chew through all scans
  87     datas = Collection(name=name, parent=parent, edit_local=parent is not None)
  88     units_dict = {"°c": "deg_C", "°f": "deg_F"}
  89     for i in range(0, len(header) - 1, 2):
  90         r = re.compile(r"[ \t\(\)]+")
  91         spl = r.split(columns[i])
  92         ax = spl[0].lower() if len(spl) > 0 else None
  93         units = spl[1].lower() if len(spl) > 1 else None
  94         units = units_dict.get(units, units)
  95         dat = datas.create_data(header[i], kind="Cary", source=filepath)
  96         dat.create_variable(ax, arr[i][~np.isnan(arr[i])], units=units)
  97         dat.create_channel(
  98             columns[i + 1].lower(), arr[i + 1][~np.isnan(arr[i + 1])], label=columns[i + 1].lower()
  99         )
  100         dat.transform(ax)
  101     # finish
  102     if verbose:
  103         print("{0} data objects successfully created from Cary file:".format(len(datas)))
  104         for i, data in enumerate(datas):
  105             print("  {0}: {1}".format(i, data))
  106     return datas
  107
  [end of WrightTools/collection/_cary.py]
  [start of examples/filters.py]
  1 #! /usr/bin/env python3
  2 # -*- coding: utf-8 -*-
  3 """
  4 Optical Filters
  5 ===============
  6 
  7 A set of optical filters transmission spectra.
  8 """
  9 
  10 import WrightTools as wt
  11 from WrightTools import datasets
  12 from matplotlib import pyplot as plt
  13 
  14 p = datasets.Cary.filters
  15 col = wt.collection.from_Cary(p)
  16 
  17 fig, gs = wt.artists.create_figure(width="double", default_aspect=.5)
  18 ax = plt.subplot(gs[0])
  19 
  20 for data in col.values():
  21     if data.natural_name in ("600LP", "550LP2"):
  22         continue
  23     data.convert("wn", verbose=False)
  24     ax.plot(data, label=data.natural_name)
  25 
  26 
  27 ax.set_ylabel("%T")
  28 ax.set_xlabel("Frequency (cm$^{-1}$)")
  29 ax.legend()
  30
  [end of examples/filters.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/WrightTools/collection/_cary.py b/WrightTools/collection/_cary.py
  --- a/WrightTools/collection/_cary.py
  +++ b/WrightTools/collection/_cary.py
  @@ -4,7 +4,7 @@
   # --- import --------------------------------------------------------------------------------------
   
   
  -import os
  +import pathlib
   import re
   
   import numpy as np
  @@ -55,14 +55,14 @@
           New data object.
       """
       # check filepath
  -    filesuffix = os.path.basename(filepath).split(".")[-1]
  -    if filesuffix != "csv":
  +    filesuffix = pathlib.Path(filepath).suffix
  +    if filesuffix != ".csv":
           wt_exceptions.WrongFileTypeWarning.warn(filepath, "csv")
       if name is None:
           name = "cary"
       # import array
       lines = []
  -    with open(filepath, "r", encoding="iso-8859-1") as f:
  +    with open(str(filepath), "r", encoding="iso-8859-1") as f:
           header = f.readline()
           columns = f.readline()
           while True:
  @@ -83,6 +83,7 @@
       header = header.split(",")
       columns = columns.split(",")
       arr = np.array(lines).T
  +    duplicate = len(header) // 2 == len(set(header) - {""})
       # chew through all scans
       datas = Collection(name=name, parent=parent, edit_local=parent is not None)
       units_dict = {"°c": "deg_C", "°f": "deg_F"}
  @@ -92,7 +93,11 @@
           ax = spl[0].lower() if len(spl) > 0 else None
           units = spl[1].lower() if len(spl) > 1 else None
           units = units_dict.get(units, units)
  -        dat = datas.create_data(header[i], kind="Cary", source=filepath)
  +        if duplicate:
  +            name = "{}_{:03d}".format(header[i], i // 2)
  +        else:
  +            name = header[i]
  +        dat = datas.create_data(name, kind="Cary", source=filepath)
           dat.create_variable(ax, arr[i][~np.isnan(arr[i])], units=units)
           dat.create_channel(
               columns[i + 1].lower(), arr[i + 1][~np.isnan(arr[i + 1])], label=columns[i + 1].lower()
  diff --git a/examples/filters.py b/examples/filters.py
  --- a/examples/filters.py
  +++ b/examples/filters.py
  @@ -1,10 +1,14 @@
   #! /usr/bin/env python3
   # -*- coding: utf-8 -*-
   """
  -Optical Filters
  -===============
  +Plotting Multiple Lines
  +=======================
   
  -A set of optical filters transmission spectra.
  +A quick demonstration of how to plot multiple lines on the same
  +set of axes, using :meth:`create_figure` to have a set of axes
  +which can plot data objects directly.
  +
  +The dataset is a set of optical filters transmission spectra.
   """
   
   import WrightTools as wt
  
verification_info: {"golden_diff": "diff --git a/WrightTools/collection/_cary.py b/WrightTools/collection/_cary.py\n--- a/WrightTools/collection/_cary.py\n+++ b/WrightTools/collection/_cary.py\n@@ -4,7 +4,7 @@\n # --- import --------------------------------------------------------------------------------------\n \n \n-import os\n+import pathlib\n import re\n \n import numpy as np\n@@ -55,14 +55,14 @@\n         New data object.\n     \"\"\"\n     # check filepath\n-    filesuffix = os.path.basename(filepath).split(\".\")[-1]\n-    if filesuffix != \"csv\":\n+    filesuffix = pathlib.Path(filepath).suffix\n+    if filesuffix != \".csv\":\n         wt_exceptions.WrongFileTypeWarning.warn(filepath, \"csv\")\n     if name is None:\n         name = \"cary\"\n     # import array\n     lines = []\n-    with open(filepath, \"r\", encoding=\"iso-8859-1\") as f:\n+    with open(str(filepath), \"r\", encoding=\"iso-8859-1\") as f:\n         header = f.readline()\n         columns = f.readline()\n         while True:\n@@ -83,6 +83,7 @@\n     header = header.split(\",\")\n     columns = columns.split(\",\")\n     arr = np.array(lines).T\n+    duplicate = len(header) // 2 == len(set(header) - {\"\"})\n     # chew through all scans\n     datas = Collection(name=name, parent=parent, edit_local=parent is not None)\n     units_dict = {\"\u00b0c\": \"deg_C\", \"\u00b0f\": \"deg_F\"}\n@@ -92,7 +93,11 @@\n         ax = spl[0].lower() if len(spl) > 0 else None\n         units = spl[1].lower() if len(spl) > 1 else None\n         units = units_dict.get(units, units)\n-        dat = datas.create_data(header[i], kind=\"Cary\", source=filepath)\n+        if duplicate:\n+            name = \"{}_{:03d}\".format(header[i], i // 2)\n+        else:\n+            name = header[i]\n+        dat = datas.create_data(name, kind=\"Cary\", source=filepath)\n         dat.create_variable(ax, arr[i][~np.isnan(arr[i])], units=units)\n         dat.create_channel(\n             columns[i + 1].lower(), arr[i + 1][~np.isnan(arr[i + 1])], label=columns[i + 1].lower()\ndiff --git a/examples/filters.py b/examples/filters.py\n--- a/examples/filters.py\n+++ b/examples/filters.py\n@@ -1,10 +1,14 @@\n #! /usr/bin/env python3\n # -*- coding: utf-8 -*-\n \"\"\"\n-Optical Filters\n-===============\n+Plotting Multiple Lines\n+=======================\n \n-A set of optical filters transmission spectra.\n+A quick demonstration of how to plot multiple lines on the same\n+set of axes, using :meth:`create_figure` to have a set of axes\n+which can plot data objects directly.\n+\n+The dataset is a set of optical filters transmission spectra.\n \"\"\"\n \n import WrightTools as wt\n", "issue": "from_Cary handle duplicate named data\nCurrently it will fail to read in data that has the same column header\n", "before_files": [{"content": "\"\"\"Cary.\"\"\"\n\n\n# --- import --------------------------------------------------------------------------------------\n\n\nimport os\nimport re\n\nimport numpy as np\n\nfrom .. import exceptions as wt_exceptions\nfrom ._collection import Collection\n\n\n# --- define --------------------------------------------------------------------------------------\n\n\n__all__ = [\"from_Cary\"]\n\n\n# --- from function -------------------------------------------------------------------------------\n\n\ndef from_Cary(filepath, name=None, parent=None, verbose=True):\n    \"\"\"Create a collection object from a Cary UV VIS absorbance file.\n\n    We hope to support as many Cary instruments and datasets as possible.\n    This function has been tested with data collected on a Cary50 UV/VIS spectrometer.\n    If any alternate instruments are found not to work as expected, please\n    submit a bug report on our `issue tracker`__.\n\n    __ github.com/wright-group/WrightTools/issues\n\n    .. plot::\n\n        >>> import WrightTools as wt\n        >>> from WrightTools import datasets\n        >>> p = datasets.Cary.CuPCtS_H2O_vis\n        >>> data = wt.collection.from_Cary(p)[0]\n        >>> wt.artists.quick1D(data)\n\n    Parameters\n    ----------\n    filepath : string\n        Path to Cary output file (.csv).\n    parent : WrightTools.Collection\n        A collection object in which to place a collection of Data objects.\n    verbose : boolean (optional)\n        Toggle talkback. Default is True.\n\n    Returns\n    -------\n    data\n        New data object.\n    \"\"\"\n    # check filepath\n    filesuffix = os.path.basename(filepath).split(\".\")[-1]\n    if filesuffix != \"csv\":\n        wt_exceptions.WrongFileTypeWarning.warn(filepath, \"csv\")\n    if name is None:\n        name = \"cary\"\n    # import array\n    lines = []\n    with open(filepath, \"r\", encoding=\"iso-8859-1\") as f:\n        header = f.readline()\n        columns = f.readline()\n        while True:\n            line = f.readline()\n            if line == \"\\n\" or line == \"\":\n                break\n            else:\n                # Note, it is necessary to call this twice, as a single call will\n                # result in something like ',,,,' > ',nan,,nan,'.\n                line = line.replace(\",,\", \",nan,\")\n                line = line.replace(\",,\", \",nan,\")\n                # Ensure that the first column has nan, if necessary\n                if line[0] == \",\":\n                    line = \"nan\" + line\n                clean = line[:-2]  # lines end with ',/n'\n                lines.append(np.fromstring(clean, sep=\",\"))\n    lines = [line for line in lines if len(line) > 0]\n    header = header.split(\",\")\n    columns = columns.split(\",\")\n    arr = np.array(lines).T\n    # chew through all scans\n    datas = Collection(name=name, parent=parent, edit_local=parent is not None)\n    units_dict = {\"\u00b0c\": \"deg_C\", \"\u00b0f\": \"deg_F\"}\n    for i in range(0, len(header) - 1, 2):\n        r = re.compile(r\"[ \\t\\(\\)]+\")\n        spl = r.split(columns[i])\n        ax = spl[0].lower() if len(spl) > 0 else None\n        units = spl[1].lower() if len(spl) > 1 else None\n        units = units_dict.get(units, units)\n        dat = datas.create_data(header[i], kind=\"Cary\", source=filepath)\n        dat.create_variable(ax, arr[i][~np.isnan(arr[i])], units=units)\n        dat.create_channel(\n            columns[i + 1].lower(), arr[i + 1][~np.isnan(arr[i + 1])], label=columns[i + 1].lower()\n        )\n        dat.transform(ax)\n    # finish\n    if verbose:\n        print(\"{0} data objects successfully created from Cary file:\".format(len(datas)))\n        for i, data in enumerate(datas):\n            print(\"  {0}: {1}\".format(i, data))\n    return datas\n", "path": "WrightTools/collection/_cary.py"}, {"content": "#! /usr/bin/env python3\n# -*- coding: utf-8 -*-\n\"\"\"\nOptical Filters\n===============\n\nA set of optical filters transmission spectra.\n\"\"\"\n\nimport WrightTools as wt\nfrom WrightTools import datasets\nfrom matplotlib import pyplot as plt\n\np = datasets.Cary.filters\ncol = wt.collection.from_Cary(p)\n\nfig, gs = wt.artists.create_figure(width=\"double\", default_aspect=.5)\nax = plt.subplot(gs[0])\n\nfor data in col.values():\n    if data.natural_name in (\"600LP\", \"550LP2\"):\n        continue\n    data.convert(\"wn\", verbose=False)\n    ax.plot(data, label=data.natural_name)\n\n\nax.set_ylabel(\"%T\")\nax.set_xlabel(\"Frequency (cm$^{-1}$)\")\nax.legend()\n", "path": "examples/filters.py"}]}