Exemple #1
0
    def test_is_square(self):
        # Test the is_square method.

        b = myokit.DataBlock2d(1, 1, [1, 2, 3])
        self.assertTrue(b.is_square())
        b = myokit.DataBlock2d(1, 2, [1, 2, 3])
        self.assertFalse(b.is_square())
        b = myokit.DataBlock2d(10, 10, [1, 2, 3])
        self.assertTrue(b.is_square())
Exemple #2
0
    def test_keys_and_items(self):
        # Test the keys0d and keys2d methods, plus the items methods.

        w = 2
        h = 3
        time = [1, 2, 3]
        b = myokit.DataBlock2d(w, h, time)

        # Test keys0d
        self.assertEqual(len(list(b.keys0d())), 0)
        pace = np.array([0, 0, 2])
        b.set0d('pace', pace)
        self.assertEqual(len(list(b.keys0d())), 1)
        self.assertEqual(len(dict(b.items0d())), 1)
        self.assertIn('pace', b.keys0d())
        b.set0d('poos', pace)
        self.assertEqual(len(list(b.keys0d())), 2)
        self.assertEqual(len(dict(b.items0d())), 2)
        self.assertIn('poos', b.keys0d())
        self.assertIn('poos', dict(b.items0d()).keys())

        # Test keys2d
        self.assertEqual(len(list(b.keys2d())), 0)
        self.assertEqual(len(dict(b.items2d())), 0)
        x = np.array([[[1, 2], [3, 4], [5, 6]], [[3, 4], [5, 6], [7, 8]],
                      [[1, 1], [2, 2], [3, 3]]])
        b.set2d('x', x)
        self.assertEqual(len(list(b.keys2d())), 1)
        self.assertEqual(len(dict(b.items2d())), 1)
        y = 3 * x + 1
        b.set2d('y', y)
        self.assertEqual(len(list(b.keys2d())), 2)
        self.assertEqual(len(dict(b.items2d())), 2)
Exemple #3
0
    def test_set0d(self):
        # Test set0d().

        w = 2
        h = 3
        time = [1, 2, 3]
        b1 = myokit.DataBlock2d(w, h, time)

        # Test valid call
        pace = np.array([0, 0, 2])
        b1.set0d('pace', pace)
        self.assertTrue(np.all(b1.get0d('pace') == pace))

        # Test copying
        b1.set0d('pace', pace, copy=False)
        self.assertTrue(np.all(b1.get0d('pace') == pace))
        self.assertIs(b1.get0d('pace'), pace)
        b1.set0d('pace', pace, copy=True)
        self.assertTrue(np.all(b1.get0d('pace') == pace))
        self.assertIsNot(b1.get0d('pace'), pace)

        # Test bad calls
        self.assertRaises(ValueError, b1.set0d, '', pace)
        self.assertRaises(ValueError, b1.set0d, 'pace', [1, 2, 3, 4])
        self.assertRaises(ValueError, b1.set0d, 'pace', np.array([1, 2, 3, 4]))
Exemple #4
0
    def block(self, log, derivatives):
        """
        Takes the output of a simulation (a simulation log and a list of
        derivatives) and combines it into a single :class:`DataBlock2d` object.

        Each entry in the log is converted to a 0d entry in the block. The
        calculated derivatives are stored as the 2d field ``derivatives``.
        """
        # Get time data
        tvar = self._model.time().qname()
        try:
            time = log[tvar]
        except KeyError:
            raise ValueError(
                'The given log must contain an entry for <' + tvar + '>.')
        # Check shape of derivatives array
        n = len(self._variables)
        m = len(self._parameters)
        shape = (len(time), n, m)
        if derivatives.shape != shape:
            raise ValueError(
                'Wrong input: Expecting a derivatives array of shape '
                + str(shape) + '.')
        # Create datablock
        block = myokit.DataBlock2d(m, n, time)
        for k, v in log.items():
            if k != tvar:
                block.set0d(k, v)
        block.set2d('derivatives', derivatives)
        return block
Exemple #5
0
    def test_to_log(self):
        # Test the `DataBlock2d.to_log()` method.

        # Create test block
        b = myokit.DataBlock2d(3, 2, [1, 2, 3, 4])
        b.set0d('pace', [0, 1, 0, 0])
        b.set2d('voltage', [[[2, 1, 0], [1, 0, 0]], [[1, 2, 1], [2, 1, 0]],
                            [[0, 1, 2], [1, 2, 1]], [[0, 0, 1], [0, 1, 2]]])

        # Convert and inspect
        d = b.to_log()
        self.assertIn('time', d)
        self.assertIn('pace', d)
        self.assertIn('0.0.voltage', d)
        self.assertIn('1.0.voltage', d)
        self.assertIn('2.0.voltage', d)
        self.assertIn('0.1.voltage', d)
        self.assertIn('1.1.voltage', d)
        self.assertIn('2.1.voltage', d)
        self.assertEqual(len(d), 8)
        self.assertEqual(list(d.time()), [1, 2, 3, 4])
        self.assertEqual(list(d['pace']), [0, 1, 0, 0])
        self.assertEqual(list(d['0.0.voltage']), [2, 1, 0, 0])
        self.assertEqual(list(d['1.0.voltage']), [1, 2, 1, 0])
        self.assertEqual(list(d['2.0.voltage']), [0, 1, 2, 1])
        self.assertEqual(list(d['0.1.voltage']), [1, 2, 1, 0])
        self.assertEqual(list(d['1.1.voltage']), [0, 1, 2, 1])
        self.assertEqual(list(d['2.1.voltage']), [0, 0, 1, 2])
Exemple #6
0
    def test_save_frame_csv(self):
        # Test the save_frame_csv() method.

        w, h = 2, 3
        time = [1, 2, 3]
        b = myokit.DataBlock2d(w, h, time)
        x = np.array([  # Each 3 by 2 array is a point in time
            [[0, 1], [2, 3], [4, 5]],
            [[5, 4], [3, 2], [1, 0]],
            [[0, 0], [0, 0], [0, 0]],
        ])
        b.set2d('x', x)

        with TemporaryDirectory() as d:
            path = d.path('test.csv')
            b.save_frame_csv(path, 'x', 0)
            with open(path, 'r') as f:
                lines = [str(x) for x in f.readlines()]
            self.assertEqual(lines[0], '"x","y","value"\n')
            self.assertEqual(lines[1], '0,0,0\n')
            self.assertEqual(lines[2], '1,0,1\n')
            self.assertEqual(lines[3], '0,1,2\n')
            self.assertEqual(lines[4], '1,1,3\n')
            self.assertEqual(lines[5], '0,2,4\n')
            self.assertEqual(lines[6], '1,2,5')
Exemple #7
0
    def test_set2d(self):
        # Test set2d().

        w = 2
        h = 3
        time = [1, 2, 3]
        b1 = myokit.DataBlock2d(w, h, time)

        # Test valid call
        x = np.array([[[1, 2], [3, 4], [5, 6]], [[3, 4], [5, 6], [7, 8]],
                      [[1, 1], [2, 2], [3, 3]]])

        b1.set2d('x', x)
        self.assertTrue(np.all(b1.get2d('x') == x))

        # Test copying
        b1.set2d('x', x, copy=False)
        self.assertTrue(np.all(b1.get2d('x') == x))
        self.assertIs(b1.get2d('x'), x)
        b1.set2d('x', x, copy=True)
        self.assertTrue(np.all(b1.get2d('x') == x))
        self.assertIsNot(b1.get2d('x'), x)

        # Test bad calls
        self.assertRaises(ValueError, b1.set2d, '', x)
        x = np.array([
            [[1, 2], [3, 4]],
            [[3, 4], [5, 6]],
            [[1, 1], [2, 2]],
        ])
        self.assertRaises(ValueError, b1.set2d, 'x', x)
Exemple #8
0
    def test_largest_eigenvalues(self):
        # Test the largest_eigenvalues method.

        # Won't work on non-square matrix
        b = myokit.DataBlock2d(1, 2, [1])
        self.assertRaises(Exception, b.largest_eigenvalues, 'x')

        # Proper test
        b = myokit.DataBlock2d(3, 3, [1])
        x = [[2, 0, 0], [0, 3, 4], [0, 4, 9]]
        b.set2d('x', [x])
        self.assertEqual(b.largest_eigenvalues('x')[0], 11)

        # Complex values
        b = myokit.DataBlock2d(3, 3, [1])
        x = [[0, 1, 0], [0, 0, 1], [1, 0, 0]]
        b.set2d('x', [x])
        self.assertAlmostEqual(b.largest_eigenvalues('x')[0], 1)
Exemple #9
0
    def test_trace(self):
        # Tests the trace() method

        w = 2
        h = 3
        time = [1, 2, 3]
        b1 = myokit.DataBlock2d(w, h, time)
        x = np.array([[[1, 2], [3, 4], [5, 6]], [[3, 4], [5, 6], [7, 8]],
                      [[1, 1], [2, 2], [3, 3]]])
        b1.set2d('x', x)
        self.assertTrue(np.all(b1.trace('x', 1, 1) == [4, 6, 2]))
Exemple #10
0
    def test_remove2d(self):
        # Test remove2d().

        # Add new 0d field and remove again
        b = myokit.DataBlock2d(2, 3, [1, 2, 3])
        x = np.array([[[1, 2], [3, 4], [5, 6]], [[3, 4], [5, 6], [7, 8]],
                      [[1, 1], [2, 2], [3, 3]]])
        self.assertEqual(b.len2d(), 0)
        b.set2d('x', np.array(x))
        self.assertEqual(b.len2d(), 1)
        b.remove2d('x')
        self.assertEqual(b.len2d(), 0)
Exemple #11
0
    def test_eigenvalues(self):
        # Test the eigenvalues method.

        # Won't work on non-square matrix
        b = myokit.DataBlock2d(1, 2, [1])
        self.assertRaises(Exception, b.eigenvalues, 'x')

        # Proper test
        b = myokit.DataBlock2d(3, 3, [1])
        x = [[2, 0, 0], [0, 3, 4], [0, 4, 9]]
        b.set2d('x', [x])
        self.assertTrue(np.all(b.eigenvalues('x') == [[11, 1, 2]]))

        # Complex values
        b = myokit.DataBlock2d(3, 3, [1])
        x = [[0, 1, 0], [0, 0, 1], [1, 0, 0]]
        b.set2d('x', [x])
        e = b.eigenvalues('x')[0]
        self.assertAlmostEqual(e[0], -0.5 - np.sqrt(3) / 2j)
        self.assertAlmostEqual(e[1], -0.5 + np.sqrt(3) / 2j)
        self.assertAlmostEqual(e[2], 1)
Exemple #12
0
    def test_dominant_eigenvalues(self):
        # Test the dominant_eigenvalues method.

        # Won't work on non-square matrix
        b = myokit.DataBlock2d(1, 2, [1])
        self.assertRaises(Exception, b.dominant_eigenvalues, 'x')

        # Proper test
        b = myokit.DataBlock2d(3, 3, [1])
        x = [[2, 0, 0], [0, 3, 4], [0, 4, 9]]
        b.set2d('x', [x])
        self.assertEqual(b.dominant_eigenvalues('x')[0], 11)

        # Complex values
        # Note: This example has complex eigenvalues, but they're not the
        # dominant ones. If they were, they'd have the same magnitude so the
        # dominant one would be undefined (and so implementation dependent,
        # which causes issues for this test. See #230).
        b = myokit.DataBlock2d(3, 3, [1])
        x = [[0.8, -0.6, 0], [0.6, 0.8, 0], [1, 2, 2]]
        b.set2d('x', [x])
        self.assertAlmostEqual(b.dominant_eigenvalues('x')[0], 2 + 0j)
Exemple #13
0
    def test_remove0d(self):
        # Test remove0d().

        # Add new 0d field and remove again
        b = myokit.DataBlock2d(2, 3, [1, 2, 3])
        self.assertEqual(b.len0d(), 0)
        b.set0d('pace', np.array([0, 0, 2]))
        self.assertEqual(b.len0d(), 1)
        b.remove0d('pace')
        self.assertEqual(b.len0d(), 0)

        # Time can't be removed
        self.assertRaises(KeyError, b.remove0d, 'time')
Exemple #14
0
    def test_bad_constructor(self):
        # Test bad arguments to a DataBlock2d raise ValueErrors.

        # Test valid constructor
        w = 2
        h = 3
        time = [1, 2, 3]
        myokit.DataBlock2d(w, h, time)

        # Test w < 1, h < 1
        self.assertRaises(ValueError, myokit.DataBlock2d, 0, h, time)
        self.assertRaises(ValueError, myokit.DataBlock2d, w, 0, time)

        # Test time matrix
        self.assertRaises(ValueError, myokit.DataBlock2d, w, h, [[1, 2, 3]])

        # Decreasing times
        self.assertRaises(ValueError, myokit.DataBlock2d, w, h, [3, 2, 1])
Exemple #15
0
    def test_images(self):
        # Test the images() method.

        w, h = 2, 2
        time = [1, 2]
        b = myokit.DataBlock2d(w, h, time)
        x = np.array([  # Each 2 by 2 array is a point in time
            [[0, 1], [2, 3]],
            [[3, 4], [4, 5]],
        ])
        b.set2d('x', x)

        # Red colormap
        t0 = np.array([  # Like colors, but strided together (ARGB32)
            255, 255, 255, 255, 204, 204, 255, 255, 153, 153, 255, 255, 102,
            102, 255, 255
        ])
        t1 = np.array([
            102,
            102,
            255,
            255,
            50,
            50,
            255,
            255,
            50,
            50,
            255,
            255,
            0,
            0,
            255,
            255,
        ])

        c = b.images('x', colormap='red')
        self.assertTrue(np.all(c[0] == t0))
        self.assertTrue(np.all(c[1] == t1))
 def jacobians(self, log):
     """
     Calculates the Jacobian matrix for each point in ``log`` and returns
     a :class:`DataBlock2d` containing all the information from the log as
     well as a 2d data series containing the jacobians (stored under the
     key "jacobians").
     
     The given :class:`DataLog` must contain logged results for all
     states in the model and any bound variables used by the model. Bound
     variables whose value does not appear in the log must be unbound before
     creating the :class:`JacobianTracer`. Only results from one-dimensional
     simulations are supported.
     """
     # Test if all states are in log
     n = None
     states = []
     for v in self._model.states():
         try:
             states.append(log[v.qname()])
         except KeyError:
             raise ValueError('Given log must contain all state variables.')
         if n is None:
             n = len(states[-1])
         elif n != len(states[-1]):
             raise ValueError('Each entry in the log must have the same'
                              ' length.')
     # Extract a value for every required input
     inputs = []
     for label in self._inputs:
         v = self._model.binding(label)
         try:
             inputs.append(log[v.qname()])
         except KeyError:
             raise ValueError('The given log must contain logged data for'
                              ' input used by the model. Missing: <' +
                              v.qname() + '> '
                              ' which is bound to ' + label + '.')
     # Create data block
     tvar = self._model.time().qname()
     try:
         time = log[tvar]
     except KeyError:
         raise ValueError('The given log must contain an entry for <' +
                          time + '>.')
     nstates = self._model.count_states()
     block = myokit.DataBlock2d(nstates, nstates, time)
     for k, v in log.iteritems():
         if k != tvar:
             block.set0d(k, v)
     # Create iterators over lists of state and input values
     istates = [iter(x) for x in states]
     iinputs = [iter(x) for x in inputs]
     # Length of derivs and partials lists
     ns = self._model.count_states()
     ns2 = ns * ns
     # Pass every state into the generator, store the output
     partials = []
     for i in xrange(n):
         state = [x.next() for x in istates]
         bound = [x.next() for x in iinputs]
         deriv = [0] * ns
         partial = [0] * ns2
         self._ext.calculate(state, bound, deriv, partial)
         # Discard derivatives
         # Convert partial derivatives to numpy array and store
         partial = np.array(partial, copy=False)
         partial = partial.reshape((ns, ns))
         partials.append(partial)
     partials = np.array(partials)
     # Create a simulation
     block.set2d('jacobians', partials, copy=False)
     return block
Exemple #17
0
    def test_combine(self):
        # Test the combine() method.

        # Create first data block
        w1, h1 = 2, 3
        t1 = [1, 2, 3]
        b1 = myokit.DataBlock2d(w1, h1, t1)
        x1 = np.array([  # Each 3 by 2 array is a point in time
            [[0, 1], [2, 3], [4, 5]],
            [[5, 4], [3, 2], [1, 0]],
            [[0, 0], [0, 0], [0, 0]],
        ])
        b1.set2d('x', x1)

        # Create first data block
        w2, h2 = 1, 2
        t2 = [1, 2, 3]
        b2 = myokit.DataBlock2d(w2, h2, t2)
        x2 = np.array([  # Each 2 by 1 array is a point in time
            [[0], [1]],
            [[2], [3]],
            [[4], [5]],
        ])
        b2.set2d('x', x2)

        # Basic combine
        m12 = {'x': ('x', 'x', -1)}
        b = myokit.DataBlock2d.combine(b1, b2, m12)
        c0 = [[0, 1, 0], [2, 3, 1], [4, 5, -1]]
        c1 = [[5, 4, 2], [3, 2, 3], [1, 0, -1]]
        c2 = [[0, 0, 4], [0, 0, 5], [0, 0, -1]]
        x = b.get2d('x')
        self.assertTrue(np.all(x[0] == c0))
        self.assertTrue(np.all(x[1] == c1))
        self.assertTrue(np.all(x[2] == c2))

        # Combine with automatic padding value
        mx = {'x': ('x', 'x')}
        b = myokit.DataBlock2d.combine(b1, b2, mx)
        c0 = [[0, 1, 0], [2, 3, 1], [4, 5, 0]]
        c1 = [[5, 4, 2], [3, 2, 3], [1, 0, 0]]
        c2 = [[0, 0, 4], [0, 0, 5], [0, 0, 0]]
        x = b.get2d('x')
        self.assertTrue(np.all(x[0] == c0))
        self.assertTrue(np.all(x[1] == c1))
        self.assertTrue(np.all(x[2] == c2))

        # Combine with pos1 and pos2 set
        m12 = {'x': ('x', 'x', -1)}
        b = myokit.DataBlock2d.combine(b1, b2, m12, pos1=(1, 0), pos2=(0, 1))
        c0 = [[-1, 0, 1], [0, 2, 3], [1, 4, 5]]
        c1 = [[-1, 5, 4], [2, 3, 2], [3, 1, 0]]
        c2 = [[-1, 0, 0], [4, 0, 0], [5, 0, 0]]
        x = b.get2d('x')
        self.assertTrue(np.all(x[0] == c0))
        self.assertTrue(np.all(x[1] == c1))
        self.assertTrue(np.all(x[2] == c2))

        # Combine with 0d information
        b1.set0d('y', [0, 10, 20])
        b2.set0d('y', [20, 30, 40])
        b = myokit.DataBlock2d.combine(b1, b2, m12, {'y': ('y', None)})
        self.assertTrue(np.all(b.get0d('y') == [0, 10, 20]))
        b = myokit.DataBlock2d.combine(b1, b2, m12, {'y': (None, 'y')})
        self.assertTrue(np.all(b.get0d('y') == [20, 30, 40]))
        self.assertRaises(ValueError, myokit.DataBlock2d.combine, b1, b2, m12,
                          {'y': ('y', 'y')})

        # Test bad time points
        b1 = myokit.DataBlock2d(w1, h1, t1)
        b2 = myokit.DataBlock2d(w2, h2, [4, 5, 6])
        self.assertRaises(ValueError, myokit.DataBlock2d.combine, b1, b2, m12)

        # Test negative pos1, bad pos2
        b1 = myokit.DataBlock2d(w1, h1, t1)
        b2 = myokit.DataBlock2d(w2, h2, t2)
        self.assertRaises(ValueError,
                          myokit.DataBlock2d.combine,
                          b1,
                          b2,
                          m12,
                          pos1=(0, -1))
        self.assertRaises(ValueError,
                          myokit.DataBlock2d.combine,
                          b1,
                          b2,
                          m12,
                          pos2=(0, -1))

        # Test overlapping pos1, bad pos2
        b1 = myokit.DataBlock2d(w1, h1, t1)
        b2 = myokit.DataBlock2d(w2, h2, t2)
        self.assertRaises(ValueError,
                          myokit.DataBlock2d.combine,
                          b1,
                          b2,
                          m12,
                          pos1=(0, 0),
                          pos2=(1, 1))
Exemple #18
0
    def test_colors_multiplier(self):
        # Test using the multiplier argument in colors

        w, h = 2, 3
        time = [1, 2, 3]
        b = myokit.DataBlock2d(w, h, time)
        x = np.array([  # Each 3 by 2 array is a point in time
            [[0, 1], [2, 3], [4, 5]],
            [[5, 4], [3, 2], [1, 0]],
            [[0, 0], [0, 0], [0, 0]],
        ])
        b.set2d('x', x)

        # Test with multiplier of 1 or less
        p = [255, 255, 255]
        q = [255, 204, 204]
        r = [255, 153, 153]
        s = [255, 102, 102]
        t = [255, 50, 50]
        u = [255, 0, 0]
        t0 = np.array([  # Deepest array is a pixel
            [p, q],
            [r, s],
            [t, u],
        ])
        t1 = np.array([
            [u, t],
            [s, r],
            [q, p],
        ])
        t2 = np.array([
            [p, p],
            [p, p],
            [p, p],
        ])
        c = b.colors('x', colormap='red', multiplier=1)
        self.assertTrue(np.all(c == np.array([t0, t1, t2])))
        c = b.colors('x', colormap='red', multiplier=1.5)
        self.assertTrue(np.all(c == np.array([t0, t1, t2])))
        c = b.colors('x', colormap='red', multiplier=0.5)
        self.assertTrue(np.all(c == np.array([t0, t1, t2])))

        t0 = np.array([
            [p, p, q, q],
            [p, p, q, q],
            [r, r, s, s],
            [r, r, s, s],
            [t, t, u, u],
            [t, t, u, u],
        ])
        t1 = np.array([
            [u, u, t, t],
            [u, u, t, t],
            [s, s, r, r],
            [s, s, r, r],
            [q, q, p, p],
            [q, q, p, p],
        ])
        t2 = np.array([
            [p, p, p, p],
            [p, p, p, p],
            [p, p, p, p],
            [p, p, p, p],
            [p, p, p, p],
            [p, p, p, p],
        ])
        c = b.colors('x', colormap='red', multiplier=2)
        self.assertTrue(np.all(c == np.array([t0, t1, t2])))

        t0 = np.array([
            [p, p, p, q, q, q],
            [p, p, p, q, q, q],
            [p, p, p, q, q, q],
            [r, r, r, s, s, s],
            [r, r, r, s, s, s],
            [r, r, r, s, s, s],
            [t, t, t, u, u, u],
            [t, t, t, u, u, u],
            [t, t, t, u, u, u],
        ])
        t1 = np.array([
            [u, u, u, t, t, t],
            [u, u, u, t, t, t],
            [u, u, u, t, t, t],
            [s, s, s, r, r, r],
            [s, s, s, r, r, r],
            [s, s, s, r, r, r],
            [q, q, q, p, p, p],
            [q, q, q, p, p, p],
            [q, q, q, p, p, p],
        ])
        t2 = np.array([
            [p, p, p, p, p, p],
            [p, p, p, p, p, p],
            [p, p, p, p, p, p],
            [p, p, p, p, p, p],
            [p, p, p, p, p, p],
            [p, p, p, p, p, p],
            [p, p, p, p, p, p],
            [p, p, p, p, p, p],
            [p, p, p, p, p, p],
        ])
        c = b.colors('x', colormap='red', multiplier=3)
        self.assertTrue(np.all(c == np.array([t0, t1, t2])))
Exemple #19
0
    def test_colors(self):
        # Test conversion to colors using different color maps.

        w, h = 2, 3
        time = [1, 2, 3]
        b = myokit.DataBlock2d(w, h, time)
        x = np.array([  # Each 3 by 2 array is a point in time
            [[0, 1], [2, 3], [4, 5]],
            [[5, 4], [3, 2], [1, 0]],
            [[0, 0], [0, 0], [0, 0]],
        ])
        b.set2d('x', x)

        # Red colormap
        t0 = np.array([  # Deepest array is a pixel
            [[255, 255, 255], [255, 204, 204]],
            [[255, 153, 153], [255, 102, 102]],
            [[255, 50, 50], [255, 0, 0]],
        ])
        t1 = np.array([
            [[255, 0, 0], [255, 50, 50]],
            [[255, 102, 102], [255, 153, 153]],
            [[255, 204, 204], [255, 255, 255]],
        ])
        t2 = np.array([
            [[255, 255, 255], [255, 255, 255]],
            [[255, 255, 255], [255, 255, 255]],
            [[255, 255, 255], [255, 255, 255]],
        ])
        c = b.colors('x', colormap='red')
        self.assertTrue(np.all(c == np.array([t0, t1, t2])))

        # Red with normalization
        t0 = np.array([
            [[255, 255, 255], [255, 255, 255]],
            [[255, 255, 255], [255, 127, 127]],
            [[255, 0, 0], [255, 0, 0]],
        ])
        t1 = np.array([
            [[255, 0, 0], [255, 0, 0]],
            [[255, 127, 127], [255, 255, 255]],
            [[255, 255, 255], [255, 255, 255]],
        ])
        t2 = np.array([
            [[255, 255, 255], [255, 255, 255]],
            [[255, 255, 255], [255, 255, 255]],
            [[255, 255, 255], [255, 255, 255]],
        ])
        c = b.colors('x', colormap='red', lower=2, upper=4)
        self.assertTrue(np.all(c[0] == t0))
        self.assertTrue(np.all(c[1] == t1))
        self.assertTrue(np.all(c[2] == t2))

        # Red with extreme normalization
        t2 = np.array([
            [[255, 255, 255], [255, 255, 255]],
            [[255, 255, 255], [255, 255, 255]],
            [[255, 255, 255], [255, 255, 255]],
        ])
        c = b.colors('x', colormap='red', lower=4, upper=4)
        self.assertTrue(np.all(c[0] == t2))
        self.assertTrue(np.all(c[1] == t2))
        self.assertTrue(np.all(c[2] == t2))

        # Green
        t0 = np.array([
            [[255, 255, 255], [204, 255, 204]],
            [[153, 255, 153], [102, 255, 102]],
            [[50, 255, 50], [0, 255, 0]],
        ])
        t1 = np.array([
            [[0, 255, 0], [50, 255, 50]],
            [[102, 255, 102], [153, 255, 153]],
            [[204, 255, 204], [255, 255, 255]],
        ])
        t2 = np.array([
            [[255, 255, 255], [255, 255, 255]],
            [[255, 255, 255], [255, 255, 255]],
            [[255, 255, 255], [255, 255, 255]],
        ])
        c = b.colors('x', colormap='green')
        self.assertTrue(np.all(c == np.array([t0, t1, t2])))

        # Blue colormap
        t0 = np.array([  # Deepest array is a pixel
            [[255, 255, 255], [204, 204, 255]],
            [[153, 153, 255], [102, 102, 255]],
            [[50, 50, 255], [0, 0, 255]],
        ])
        t1 = np.array([
            [[0, 0, 255], [50, 50, 255]],
            [[102, 102, 255], [153, 153, 255]],
            [[204, 204, 255], [255, 255, 255]],
        ])
        t2 = np.array([
            [[255, 255, 255], [255, 255, 255]],
            [[255, 255, 255], [255, 255, 255]],
            [[255, 255, 255], [255, 255, 255]],
        ])
        c = b.colors('x', colormap='blue')
        self.assertTrue(np.all(c == np.array([t0, t1, t2])))

        # Rainbow/traditional colormap
        t0 = np.array([  # Deepest array is a pixel
            [[153, 61, 143], [49, 35, 212]],
            [[4, 235, 249], [4, 250, 14]],
            [[209, 213, 35], [153, 61, 61]],
        ])
        t1 = np.array([
            [[153, 61, 61], [209, 213, 35]],
            [[4, 250, 14], [4, 235, 249]],
            [[49, 35, 212], [153, 61, 143]],
        ])
        t2 = np.array([
            [[153, 61, 143], [153, 61, 143]],
            [[153, 61, 143], [153, 61, 143]],
            [[153, 61, 143], [153, 61, 143]],
        ])
        c = b.colors('x', colormap='traditional')
        self.assertTrue(np.all(c[0] == t0))
        self.assertTrue(np.all(c[1] == t1))
        self.assertTrue(np.all(c[2] == t2))