diff --git a/VERSION b/VERSION
index b9c6c007cc10d619b2d858dcc4ae12ba790b52a2..dd1ec209f3358043353ec9054f1d3bf3416d325e 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-131
\ No newline at end of file
+132
\ No newline at end of file
diff --git a/lib/+artoa/+controller/+edit/+offsets/buttonCalculateOffsets.m b/lib/+artoa/+controller/+edit/+offsets/buttonCalculateOffsets.m
index d541802ff28a2ae726c7ccb594f3f586096bd2e6..f6b0c6783e5e908fb2ba891dc92cb9825ca74587 100644
--- a/lib/+artoa/+controller/+edit/+offsets/buttonCalculateOffsets.m
+++ b/lib/+artoa/+controller/+edit/+offsets/buttonCalculateOffsets.m
@@ -14,7 +14,8 @@ satData = artoaWorkspace.satData;
     artoaWorkspace.editOffsets.A, ...
     artoaWorkspace.editOffsets.B, ...
     artoaWorkspace.editOffsets.X, ...
-    ~ ...
+    artoaWorkspace.editOffsets.unfilteredA, ...
+    artoaWorkspace.editOffsets.unfilteredB ...
 ] = artoa.offsets.solve( ...
     artoaDataInput.rfb, ...
     soundsources, ...
diff --git a/lib/+artoa/+controller/+file/saveOptimumTables.m b/lib/+artoa/+controller/+file/saveOptimumTables.m
new file mode 100644
index 0000000000000000000000000000000000000000..2028b3a21be15bf87cbba22227bdc7523846bb20
--- /dev/null
+++ b/lib/+artoa/+controller/+file/saveOptimumTables.m
@@ -0,0 +1,33 @@
+function [] = saveOptimumTables(~, ~)
+%SAVERFC Summary of this function goes here
+%   Detailed explanation goes here
+
+global artoaWorkspace artoaDataInput;
+
+%% Get offsets
+unfilteredA = artoa.data.getMember(artoaWorkspace, {'editOffsets', 'unfilteredA'}, false);
+unfilteredB = artoa.data.getMember(artoaWorkspace, {'editOffsets', 'unfilteredB'}, false);
+A = artoa.data.getMember(artoaWorkspace, {'editOffsets', 'A'}, false);
+B = artoa.data.getMember(artoaWorkspace, {'editOffsets', 'B'}, false);
+X = artoa.data.getMember(artoaWorkspace, {'editOffsets', 'X'}, false);
+
+if islogical(unfilteredA) || islogical(unfilteredB) ...
+        || islogical(A) || islogical(B) || islogical(X)
+    errordlg('At least one of the matrices to save is not available. Please recalculate!', 'Matrices not found');
+    return;
+end
+
+%% Get required variables
+folder = artoa.data.getMember(artoaDataInput, {'ini', 'directory', 'optimumtables'}, pwd());
+filter = artoa.data.getMember(artoaDataInput, {'ini', 'filemask', 'optimumtables'}, '*.mat');
+
+%% Ask for filename
+[filename, pathname] = uiputfile(fullfile(folder, filter));
+
+filepath = fullfile(pathname, filename);
+
+save(filepath, 'unfilteredA', 'unfilteredB', 'A', 'B', 'X');
+
+
+end
+
diff --git a/lib/+artoa/+controller/+main/open.m b/lib/+artoa/+controller/+main/open.m
index 0784c9c7b30f8ceaddb755e823e517b07fa9120e..4d4e68ddfc151c533040cb2941e22b024656dfd7 100644
--- a/lib/+artoa/+controller/+main/open.m
+++ b/lib/+artoa/+controller/+main/open.m
@@ -21,6 +21,7 @@ callbacks.loadInterim = @artoa.controller.file.loadInterim;
 callbacks.loadSoundsourceFile = @artoa.controller.file.loadSoundSourceFile;
 callbacks.saveRfc = @artoa.controller.file.saveRfc;
 callbacks.saveInterim = @artoa.controller.file.saveInterim;
+callbacks.saveOptimumTables = @artoa.controller.file.saveOptimumTables;
 callbacks.loadArtoaIni = @artoa.controller.file.loadArtoaIni;
 callbacks.openEditTemperature = @artoa.controller.edit.temperature.open;
 callbacks.openEditPressure = @artoa.controller.edit.pressure.open;
diff --git a/lib/+artoa/+gui/main.m b/lib/+artoa/+gui/main.m
index e6dd5dd6b0af661d6041bb3243205590b29b6811..1ba00e0c80f2f843f19ceacc07c57d7575345525 100644
--- a/lib/+artoa/+gui/main.m
+++ b/lib/+artoa/+gui/main.m
@@ -13,6 +13,7 @@ availableCallbacks = { ...
     'loadSoundsourceFile', ...
     'saveRfc', ...
     'saveInterim', ...
+    'saveOptimumTables', ...
     'loadArtoaIni', ...
     'quit', ...
     'openEditTemperature', ...
@@ -90,6 +91,12 @@ uimenu( ...
     'Callback', pCallbacks.saveInterim ...
 );
 
+uimenu( ...
+    artoaGui.main.menus.fileSave, ...
+    'Label', 'Optimum tables', ...
+    'Callback', pCallbacks.saveOptimumTables ...
+);
+
 artoaGui.main.menus.fileReloadArtoaIni = uimenu( ...
     artoaGui.main.menus.file, ...
     'Label', 'Reload artoa.ini', ...
diff --git a/lib/+artoa/+offsets/solve.m b/lib/+artoa/+offsets/solve.m
index 47e50d9866a86d1f7d60dbb60abecf63c1ad2dad..bc02ca6dbe7115e529e2433ca807a3a0773ce718 100644
--- a/lib/+artoa/+offsets/solve.m
+++ b/lib/+artoa/+offsets/solve.m
@@ -1,9 +1,9 @@
-function [A, B, X, unfilteredA] = solve(pRfb, pSoundsources, pTrackingParameter, pToaData, pSatData, pAppliedTemperature, pAppliedPressure, pLeapsecondsMatrix, pOffsetsParameter)
+function [A, B, X, unfilteredA, unfilteredB] = solve(pRfb, pSoundsources, pTrackingParameter, pToaData, pSatData, pAppliedTemperature, pAppliedPressure, pLeapsecondsMatrix, pOffsetsParameter)
 %UNTITLED Summary of this function goes here
 %   Detailed explanation goes here
 
 %% Construct matrices A and B
-[unfilteredA, B] = artoa.offsets.createCalculationTables( ...
+[unfilteredA, unfilteredB] = artoa.offsets.createCalculationTables( ...
     pRfb, ...
     pSoundsources, ...
     pTrackingParameter, ...
@@ -17,7 +17,7 @@ function [A, B, X, unfilteredA] = solve(pRfb, pSoundsources, pTrackingParameter,
 %% Subtract all known offsets
 [B] = artoa.offsets.subtractKnownOffsets( ...
     unfilteredA, ...
-    B, ...
+    unfilteredB, ...
     pOffsetsParameter.offsets ...
 );