An avenue that I am currently pursuing is taking the pressure data from Tyler by means of my modifications to Tactonic's source code and translating it into audio output. The end-goal here is to use that program to show that a unique signal can be produced from a particular set of pressure data.
Dr. Remy has suggested that I implement this in Python, and the current work on this is being written using Python 2.7.3.
The major problems that this code must solve are:
- Distinguishing between and grabbing pressure groups
- Modulating audio output based on pressure data
As of now, pressure data is being received in a (w * h)n array of integers, where n is the number of pressure sensors and w and h represent the number of sensors in a row or column of sensors, respectively. The test data currently being used is:
The array generated by Tyler is presented as a single string where elements are delimited by either a single space or a newline character. This data allows for a not-quite-rigorous test of group-grabbing code because, despite its appearance, it actually contains three groups.
How is a group defined?A group, as I mean here, is a contiguous set of nonzero data points adjacent to each other on a Cartesian plane. This definition presents its own challenges. A group can be of any shape so long as each point is adjacent to at least one other point in the group. Any nonzero point that is not adjacent to another point is in its own group. This means that a group can consist of a single point. In the future, more constraints may be added, but for the time being this definition is sufficient for generating code that can handle grabbing groups out of an array.
One example of a decision to make concerning this definition is determining whether or not elements that are "diagonal" will count as adjacent. For the time being, adjacency is limited to points (x - 1, y), (x + 1, y), (x, y - 1), and (x, y + 1).
Implemented in Python, this looks like:
class Group:
"""Group represents a set of points with some relation to one another. In
addition to the point list, it calculates the coordinates of the center of
the group."""
def __init__(self, cx=0.0, cy=0.0):
self.point_list = []
self.center = [cx, cy]
The class stores a list of Point objects and a list of coordinates representing the center of the group.
The Point class is simply a storage class that keeps a pair of coordinates and the data stored at those coordinates.
class Point:
"""Point represents one unit of data on a Cartesian plane. In addition to
coordinate information, it stores the data recorded at the point"""
def __init__(self, x=0, y=0, d=0):
self.coords = (x,y) #These do not need to change
self.data = d #This is expected to change
What information must a group contain?Per the definition above, a Group storage type must contain all points within the group and their force data. In addition, groups will contain the coordinates of their center of pressure. This is determined by
CenterX = sum(x * force(x)) / sum(force)
CenterY = sum(y * force(y)) / sum(force)
This is calculated by iterating over the entire group and summing the necessary components at each point. This operation has been rewritten for Python as:
def calculate_center(self):
force = 0.0
for p in self.point_list:
force += p.data
self.center[0] += float(p.data) * float(p.coords[0])
self.center[1] += float(p.data) * float(p.coords[1])
self.center = [_ / force for _ in self.center]
Looking ForwardThe main concern at this point is writing an efficient group-grabbing algorithm. A successful algorithm will be able to pull a group from the array in a single pass with no information about the shape of a group, and it will create no duplicate groups or groups whose points overlap.
As of now, the code pulls information from a text file, but the eventual goal is to be able to read from an array posted online. This functionality will need to be implemented once Tyler is able to interface with the Raspberry Pi.
I have written tentative code for both classes mentioned above. The entirety of the code for those classes as of now is as follows:
class Point:
"""Point represents one unit of data on a Cartesian plane. In addition to
coordinate information, it stores the data recorded at the point"""
def __init__(self, x=0, y=0, d=0):
self.coords = (x,y) #These do not need to change
self.data = d #This is expected to change
def compare(self, p):
return (self.coords == p.coords and self.data == p.data)
def print_point(self):
print '{0:3d} {1:3d} {2:4d}\n'.format(self.coords[0], self.coords[1],
self.data)
class Group:
"""Group represents a set of points with some relation to one another. In
addition to the point list, it calculates the coordinates of the center of
the group."""
def __init__(self, cx=0.0, cy=0.0):
self.point_list = []
self.center = [cx, cy]
def add_point(self, x, y, d):
self.point_list.append(Point(x, y, d))
def calculate_center(self):
force = 0.0
for p in self.point_list:
force += p.data
self.center[0] += float(p.data) * float(p.coords[0])
self.center[1] += float(p.data) * float(p.coords[1])
self.center = [_ / force for _ in self.center]
def contains(self, x, y, d):
p = Point(x, y, d)
for point in self.point_list:
if p.compare(point):
del p
return True
del p
return False
def print_group_data(self):
for point in self.point_list:
point.print_point()
print "Center {}".format(self.center)