Skip to content

Commit

Permalink
Add some changes by Michael Stanway fron #51
Browse files Browse the repository at this point in the history
This PR tries to apply some changes earlier attempted by Michael Stanway and shown in PR #51 but in a accurate way, and also adding some tests
--------
Co-authored-by: Tate Dunbar
  • Loading branch information
tatedunbar authored Apr 2, 2024
1 parent 1b1009b commit 7dabc9d
Show file tree
Hide file tree
Showing 8 changed files with 180 additions and 16 deletions.
2 changes: 1 addition & 1 deletion ARTwarp.m
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,4 @@
network = NetworkFactory.new_network(contours);

% Run in Network instance (the rest of run_categorisation.m)
% sub function includes (activate, add_new, calc_match, update_weights)
% sub function includes (activate, add_new, calc_match, update_weights)
35 changes: 31 additions & 4 deletions Category.m
Original file line number Diff line number Diff line change
Expand Up @@ -17,22 +17,49 @@
cat.reference = reference;
end

function val = compare(contour)
function val = compare(cat, contour)
val = 0;
% Compare a given contour object with the reference contour and
% return a percentage match value
% TODO
end

function add(contour)
function cat = add(cat, contour)
% Update the reference contour with the given new contour and
% increment the size
% TODO
cat.reference = cat.average(contour);
cat.size = cat.size + 1;
end

function remove(contour)
function cat = remove(cat, contour)
% Update the reference contour to remove the given contour and
% decrement the size
cat.reference = cat.unaverage(contour);
cat.size = cat.size - 1;

% If the number of contours in the category drops below 1,
% empty the reference contour
if cat.size == 0
cat.reference = [];
end
end

function avg = average(cat, contour)
% Calculate the reference contour for the category with a new
% contour added
% TODO

% Temporary, for testing purposes
avg = cat.reference;
end

function avg = unaverage(cat, contour)
% Calculate the reference contour for the category with an old
% contour removed
% TODO

% Temporary, for testing purposes
avg = cat.reference;
end
end
end
Expand Down
7 changes: 4 additions & 3 deletions Contour.m
Original file line number Diff line number Diff line change
Expand Up @@ -11,20 +11,21 @@
frequency % An array of frequency values
tempres % Sample rate of frequency
length % The number of frequency samples
category {mustBeInteger} = 0 % The category index this contour is
% organised into, initially 0
category % The category this contour is
% organised into
warpFunction % The warp function of the contour, will be used to
% re-calculate the average after this contour is add or removed
% from its category
end

methods (Static)
function obj = Contour(frequency, tempres, length)
function obj = Contour(frequency, tempres, length, warpFunction)
% Constructs a new contour object with a given array of
% frequency values, temporal resolution, and length
obj.frequency = frequency;
obj.tempres = tempres;
obj.length = length;
obj.warpFunction = warpFunction;
end
end
end
4 changes: 2 additions & 2 deletions ContourFactory.m
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
frequency = contents.PeakFrequency_Hz_;
ctrLen = size(frequency, 1);
tempres = (contents.Time_ms_(ctrLen) - contents.Time_ms_(1)) / ctrLen;
contours = [contours, Contour(frequency, tempres, ctrLen)]; %#ok<*AGROW> % ignore warning until better solution found
contours = [contours, Contour(frequency, tempres, ctrLen, 0)]; %#ok<*AGROW> % ignore warning until better solution found
end
end

Expand All @@ -43,7 +43,7 @@
frequency = transpose(contents.freqContour);
tempres = contents.tempres;
ctrLen = size(frequency, 1);
contours = [contours, Contour(frequency, tempres, ctrLen)];
contours = [contours, Contour(frequency, tempres, ctrLen, 0)];
end
end
end
Expand Down
75 changes: 72 additions & 3 deletions Network.m
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,90 @@

properties
weights

categories % Categories within the network
num_categories % Number of categories in the network
reclassifications % Number of reclassifications which have occurred
end

methods
function obj = Network(weights)
obj.weights = weights;
obj.num_categories = 0;
obj.categories = [];
end

function add(contour)
function obj = update_network(obj, contour, parameters)
% Add a contour object to the network
% Iterates through the current categories and adds the
% contour to the one it is most similar to; if it matches
% none of them, create a new category for the contour

% TODO
% Find category in network that contour fits into
matched_category = find_category(obj, contour, parameters);

% If there is no category the contour fits into, create a new
% one, with the contour as the reference for it.
if matched_category == -1
new_category = Category.category(1, contour);
obj = obj.add_category(new_category);

% Alter category property of contour
contour.category = new_category;

% If the contour was already in a category, remove it
if(contour.category) ~= 0
obj.categories(contour.category) = obj.categories(contour.category).remove(contour.category, contour);
end

% Increment number of reclassifications
obj.reclassifications = obj.reclassifications + 1;
elseif matched_category ~= contour.category
% Remove from old category if moved to new category
obj.categories(contour.category) = obj.categories(contour.category).remove(contour.category, contour);

% Add to new category
obj.categories(matched_category) = obj.categories(matched_category).add(contour.category, contour);

% Alter category property of contour
contour.category = matched_category;

% Increment number of reclassifications
obj.reclassifications = obj.reclassifications + 1;
end

end

function matched_category = find_category(obj, contour, parameters)
% Find the category a new contour fits into

% If there are no categories, no match found (-1 returned)
if obj.num_categories == 0
matched_category = -1;
else
% Create array for storing matches
a = zeros(1, obj.num_categories);

% Calculate matches
for i = 1:obj.num_categories
a(i) = obj.categories(i).compare(contour);
end

% Find max match percentage and see if it is above
% vigilance, return -1 if not
[max_match, matched_category] = max(a);

if max_match < parameters.vigilance
matched_category = -1;
end
end
end

function obj = add_category(obj,cat)
% Add new category to categories list in Network
obj.categories = [obj.categories, cat];

% Increase number of categories in the Network
obj.num_categories = obj.num_categories + 1;
end
end
end
Expand Down
35 changes: 34 additions & 1 deletion NetworkFactory.m
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

methods (Static)
function net = new_network(contours)
% Creates an empty
% Creates an empty network
weights = ones(max([contours.length]), 0);
net = Network(weights);
end
Expand All @@ -13,6 +13,39 @@
% Load a saved network
% TODO: no idea how we would store networks
end

function net = run_categorisation(network, contours, parameters)
% This will run the network until all contours have been
% categorised and an iteration has completed with no reclassifications

% NOTE: contour list should be randomised before entered into this function

network.reclassifications = 0;
iteration_number = 1;
a = 0;

while(a == 0 && iteration_number < parameters.maxNumIterations)
% Set the number of reclassifications for the iteration to
% zero
network.reclassifications = 0;

% Run through this iteration, updating the network with each contour in the list
for i = 1:length(contours)
network = network.update_network(contours(i), parameters);
end

% Increment iteration number
iteration_number = iteration_number + 1;

% Break out of loop if no reclassifications done (categorisation complete)
if network.reclassifications == 0
a = 1;
end
end

% assign net as completed network
net = network;
end

end
end
Expand Down
27 changes: 25 additions & 2 deletions tst/category_test.m
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,32 @@

contours = ContourFactory.load_contours(dir_path);

%make new category with size of 1 and the first contour as the reference
% Make new category with size of 1 and the first contour as the reference
cat = Category(1, contours(1));

%assert that initialization has occurred properly
% Assert that initialization has occurred properly
assert(cat.size == 1, "Problem with initializing size");
assert(isequal(cat.reference, contours(1)), "Problem with initializing reference contour");

% Add another contour
cat = cat.add(contours(2));

% Assert size has increased
% Once average has been implemented, should also check that the new
% reference is correct
assert(cat.size == 2, "Problem with increasing size after addition of contour");

% Remove contour
cat = cat.remove(contours(2));

% Assert size has decreased
% Once unaverage has been implemented, should also check that the new
% reference is correct
assert(cat.size == 1, "Problem with decreasing size after removal of contour");

% Remove another contour, making category empty
cat = cat.remove(contours(1));

% Assert size is now 0 and reference contour is empty
assert(cat.size == 0, "Problem with decreasing size after removal of contour");
assert(isempty(cat.reference), "Problem with emptying reference contour when category is empty");
11 changes: 11 additions & 0 deletions tst/network_test.m
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,16 @@
contours = ContourFactory.load_contours(dir_path);
assert(length(contours) == 7, "Problems with getting all contours");

parameters = Parameters();

network = NetworkFactory.new_network(contours);
assert(isequal(size(network.weights), [1050 0]), "Problem with generating new network")

% Test adding category to Network
cat = Category(2,contours(1));
network = network.add_category(cat);
assert(isequal(network.num_categories, 1), "Problem with changing number of categories.");
assert(isequal(network.categories(network.num_categories), cat), "Problem with adding category.");

% Further tests can be added after compare function in Category.m has been
% implemented

0 comments on commit 7dabc9d

Please sign in to comment.