prompt: You will be provided with a partial code base and an issue statement explaining a problem to resolve.
  <issue>
  Different ordering of channels between model.config.channels and mode.config.channel_nbins
  # Description
  
  We've recently observed that the ordering of channels outputted from `model.config.channels` differs from the order obtained with `model.config.channel_nbins`. This isn't really a bug, but more a quirk which we thought would be worth bringing to the attention of the developers. We ran into some issues when breaking up the `expected_data` list into individual channels by looping through the `model.config.channel_nbins` ordering, rather than the `model.config.channels` ordering (the `model.config.channels` order matches that of the model). Hopefully this issue helps save another user some time in the future, at very least. 
  
  # Expected Behavior
  
  We expected that the order of the channels in the two dictionaries from `model.config.channels` and `model.config.channel_nbins` would be the same. 
  
  # Actual Behavior
  
  The ordering of the channels is different. As an example, we are generating workspaces using two categories, and we're separating our data by year (2016, 2017, and 2018). This gives us six channels total. The outputs are: 
  ```
  (Pdb) model.config.channels
  ['vbf_channel_16_high_cat', 'vbf_channel_16_low_cat', 'vbf_channel_17_high_cat', 'vbf_channel_17_low_cat', 'vbf_channel_18_high_cat', 'vbf_channel_18_low_cat']
  
  (Pdb) model.config.channel_nbins
  {'vbf_channel_16_low_cat': 12, 'vbf_channel_16_high_cat': 18, 'vbf_channel_17_low_cat': 12, 'vbf_channel_17_high_cat': 18, 'vbf_channel_18_low_cat': 12, 'vbf_channel_18_high_cat': 18}
  ```
  I believe that `model.config.channels` is possibly re-ordering the channels so that the names are in alphabetical order. I have not confirmed this, though. The workspace .json file is filled with the ordering produced by `model.config.channel_nbins`. 
  
  # Steps to Reproduce
  
  I'm using pyhf version 0.6.2 along with python 3.8.8. 
  I can make a dummy workspace for this issue, but I thought that since this is a pretty small issue, it might be overkill. Please let me know if this would be helpful, though. 
  
  # Checklist
  
  - [ ] Run `git fetch` to get the most up to date version of `master`
  - [X] Searched through existing Issues to confirm this is not a duplicate issue
  - [X] Filled out the Description, Expected Behavior, Actual Behavior, and Steps to Reproduce sections above or have edited/removed them in a way that fully describes the issue
  
  
  Thanks! -Rachel 
  
  
  </issue>
  <code>
  [start of src/pyhf/mixins.py]
  1 import logging
  2 
  3 log = logging.getLogger(__name__)
  4 
  5 
  6 class _ChannelSummaryMixin:
  7     """
  8     A mixin that provides summary data of the provided channels.
  9 
  10     This mixin will forward all other information to other classes defined in the Child class.
  11 
  12     Args:
  13       **channels: A list of channels to provide summary information about. Follows the `defs.json#/definitions/channel` schema.
  14     """
  15 
  16     def __init__(self, *args, **kwargs):
  17         channels = kwargs.pop('channels')
  18         super().__init__(*args, **kwargs)
  19         self.channels = []
  20         self.samples = []
  21         self.parameters = []
  22         self.modifiers = []
  23         # keep track of the width of each channel (how many bins)
  24         self.channel_nbins = {}
  25         # need to keep track in which order we added the constraints
  26         # so that we can generate correctly-ordered data
  27         for channel in channels:
  28             self.channels.append(channel['name'])
  29             self.channel_nbins[channel['name']] = len(channel['samples'][0]['data'])
  30             for sample in channel['samples']:
  31                 self.samples.append(sample['name'])
  32                 for modifier_def in sample['modifiers']:
  33                     self.parameters.append(modifier_def['name'])
  34                     self.modifiers.append(
  35                         (
  36                             modifier_def['name'],  # mod name
  37                             modifier_def['type'],  # mod type
  38                         )
  39                     )
  40 
  41         self.channels = sorted(list(set(self.channels)))
  42         self.samples = sorted(list(set(self.samples)))
  43         self.parameters = sorted(list(set(self.parameters)))
  44         self.modifiers = sorted(list(set(self.modifiers)))
  45 
  46         self.channel_slices = {}
  47         begin = 0
  48         for c in self.channels:
  49             end = begin + self.channel_nbins[c]
  50             self.channel_slices[c] = slice(begin, end)
  51             begin = end
  52
  [end of src/pyhf/mixins.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/src/pyhf/mixins.py b/src/pyhf/mixins.py
  --- a/src/pyhf/mixins.py
  +++ b/src/pyhf/mixins.py
  @@ -42,6 +42,9 @@
           self.samples = sorted(list(set(self.samples)))
           self.parameters = sorted(list(set(self.parameters)))
           self.modifiers = sorted(list(set(self.modifiers)))
  +        self.channel_nbins = {
  +            channel: self.channel_nbins[channel] for channel in self.channels
  +        }
   
           self.channel_slices = {}
           begin = 0
  
verification_info: {"golden_diff": "diff --git a/src/pyhf/mixins.py b/src/pyhf/mixins.py\n--- a/src/pyhf/mixins.py\n+++ b/src/pyhf/mixins.py\n@@ -42,6 +42,9 @@\n         self.samples = sorted(list(set(self.samples)))\n         self.parameters = sorted(list(set(self.parameters)))\n         self.modifiers = sorted(list(set(self.modifiers)))\n+        self.channel_nbins = {\n+            channel: self.channel_nbins[channel] for channel in self.channels\n+        }\n \n         self.channel_slices = {}\n         begin = 0\n", "issue": "Different ordering of channels between model.config.channels and mode.config.channel_nbins\n# Description\r\n\r\nWe've recently observed that the ordering of channels outputted from `model.config.channels` differs from the order obtained with `model.config.channel_nbins`. This isn't really a bug, but more a quirk which we thought would be worth bringing to the attention of the developers. We ran into some issues when breaking up the `expected_data` list into individual channels by looping through the `model.config.channel_nbins` ordering, rather than the `model.config.channels` ordering (the `model.config.channels` order matches that of the model). Hopefully this issue helps save another user some time in the future, at very least. \r\n\r\n# Expected Behavior\r\n\r\nWe expected that the order of the channels in the two dictionaries from `model.config.channels` and `model.config.channel_nbins` would be the same. \r\n\r\n# Actual Behavior\r\n\r\nThe ordering of the channels is different. As an example, we are generating workspaces using two categories, and we're separating our data by year (2016, 2017, and 2018). This gives us six channels total. The outputs are: \r\n```\r\n(Pdb) model.config.channels\r\n['vbf_channel_16_high_cat', 'vbf_channel_16_low_cat', 'vbf_channel_17_high_cat', 'vbf_channel_17_low_cat', 'vbf_channel_18_high_cat', 'vbf_channel_18_low_cat']\r\n\r\n(Pdb) model.config.channel_nbins\r\n{'vbf_channel_16_low_cat': 12, 'vbf_channel_16_high_cat': 18, 'vbf_channel_17_low_cat': 12, 'vbf_channel_17_high_cat': 18, 'vbf_channel_18_low_cat': 12, 'vbf_channel_18_high_cat': 18}\r\n```\r\nI believe that `model.config.channels` is possibly re-ordering the channels so that the names are in alphabetical order. I have not confirmed this, though. The workspace .json file is filled with the ordering produced by `model.config.channel_nbins`. \r\n\r\n# Steps to Reproduce\r\n\r\nI'm using pyhf version 0.6.2 along with python 3.8.8. \r\nI can make a dummy workspace for this issue, but I thought that since this is a pretty small issue, it might be overkill. Please let me know if this would be helpful, though. \r\n\r\n# Checklist\r\n\r\n- [ ] Run `git fetch` to get the most up to date version of `master`\r\n- [X] Searched through existing Issues to confirm this is not a duplicate issue\r\n- [X] Filled out the Description, Expected Behavior, Actual Behavior, and Steps to Reproduce sections above or have edited/removed them in a way that fully describes the issue\r\n\r\n\r\nThanks! -Rachel \r\n\n", "before_files": [{"content": "import logging\n\nlog = logging.getLogger(__name__)\n\n\nclass _ChannelSummaryMixin:\n    \"\"\"\n    A mixin that provides summary data of the provided channels.\n\n    This mixin will forward all other information to other classes defined in the Child class.\n\n    Args:\n      **channels: A list of channels to provide summary information about. Follows the `defs.json#/definitions/channel` schema.\n    \"\"\"\n\n    def __init__(self, *args, **kwargs):\n        channels = kwargs.pop('channels')\n        super().__init__(*args, **kwargs)\n        self.channels = []\n        self.samples = []\n        self.parameters = []\n        self.modifiers = []\n        # keep track of the width of each channel (how many bins)\n        self.channel_nbins = {}\n        # need to keep track in which order we added the constraints\n        # so that we can generate correctly-ordered data\n        for channel in channels:\n            self.channels.append(channel['name'])\n            self.channel_nbins[channel['name']] = len(channel['samples'][0]['data'])\n            for sample in channel['samples']:\n                self.samples.append(sample['name'])\n                for modifier_def in sample['modifiers']:\n                    self.parameters.append(modifier_def['name'])\n                    self.modifiers.append(\n                        (\n                            modifier_def['name'],  # mod name\n                            modifier_def['type'],  # mod type\n                        )\n                    )\n\n        self.channels = sorted(list(set(self.channels)))\n        self.samples = sorted(list(set(self.samples)))\n        self.parameters = sorted(list(set(self.parameters)))\n        self.modifiers = sorted(list(set(self.modifiers)))\n\n        self.channel_slices = {}\n        begin = 0\n        for c in self.channels:\n            end = begin + self.channel_nbins[c]\n            self.channel_slices[c] = slice(begin, end)\n            begin = end\n", "path": "src/pyhf/mixins.py"}]}