Moving on from making adjustments to the values within the array data we next consider
operations that can add and remove whole signal layers. Naturally it is possible to create
one Microarray object with different channels based on another, manipulating the signal
data outside the class. Hence, for example, we could take the red and green (index 0 and
1) layers from one object and construct another, here making an array which visualises as
yellow and blue:
red = rgArray.data[0]
green = rgArray.data[1]
yellowBlue = Microarray('yellowBlue', [red, red, green])
yellowBlue.makeImage(20).show()
However, in keeping with the object-oriented approach, we can add any general
functionality to the Microarray class as methods. As examples we will add functions that
replace, add and remove complete layers of array data (i.e. corresponding to one colour
channel). Though, in the situations where we are supplying new values the input data must
be of the correct size to be added to the array. In order to guarantee this we first describe
the checkDataSize() function, which will trigger an error if the input for a layer is not of
the same size as the existing array data. This function first makes an array() copy of the
data, in case it was input as lists or tuples, and then the input size (accessed with .shape)
must naturally match the number of rows and columns.
def checkDataSize(self, channelData):
channelData = array(channelData)
if channelData.shape != (self.nRows, self.nCols):
msg = 'Attempt to use data of wrong size'
raise Exception(msg)
return channelData
With the above function available to check any input we now add the functions to
change the array layers. First setChannel() is constructed to replace all the data for an
array layer specified at a given (existing) index.
def setChannel(self, channelData, index=0):
channelData = self.checkDataSize(channelData)
self.data[index] = channelData
The second function adds an entirely new layer of array data after the existing data.
This involves using the NumPy function append() with the setting axis=0 to create a new
larger array (along the first axis). The self.nChannels attribute that records the number of
individual layers is naturally incremented to keep consistency.
def addChannel(self, channelData):
from numpy import append
channelData = self.checkDataSize(channelData)
self.data = append(self.data, channelData, axis=0)
self.nChannels += 1
The function to swap channels takes two indices (which we really ought to check are
valid) and uses tuples to index subsets of the NumPy arrays, i.e. assign the layer values
which were at indexA to indexB, and vice versa.
def swapChannels(self, indexA, indexB):
self.data[(indexB, indexA)] = self.data[(indexA, indexB)]
The function to remove a layer uses the NumPy delete() function, noting that this does
not change the input arrays, but rather gives back a new array with the required part
removed, which we then assign to self.data.
def removeChannel(self, index):
from numpy import delete
if index < self.nChannels:
self.data = delete(self.data, index, axis=0)
self.nChannels −= 1
Lastly there is a function to combine two channels specified via indices. This has a
combFunc option to specify how the layers should be combined, which otherwise defaults
to addition. If a special combFunc is passed in it must be the name of a function that
accepts two equal-size NumPy arrays to perform the combination operation and creates
another array of the same size. The replace option states which layer the new, combined
data should be put into. This could be an entirely new layer, if the value is left as None, or
it replaces an existing layer given an index. The required addition or replacement
operation is easily achieved by using the existing methods we discussed above.
def combineChannels(self, indexA, indexB, combFunc=None, replace=None):
if not combFunc:
import operator
combFunc= operator.add
channelData = combFunc(self.data[indexA], self.data[indexB])
if replace is None:
self.addChannel(channelData)
else:
self.setChannel(channelData, replace)
We can test the above function using the example red and green data:
imgFile = 'examples/RedGreenArray.png'
testArray = loadArrayImage(imgFile, 'TwoChannel', 18, 17)
# Red and green added to channel 2
testArray.combineChannels(0, 1, replace=2)
# Display channel 2 as yellow
testArray.makeImage(20, channels=(2, 2, None)).show()