diff --git a/Measurement and analysis routines/AmplNoiseCal/GuiAmplNoiseCal.mlapp b/Measurement and analysis routines/AmplNoiseCal/GuiAmplNoiseCal.mlapp new file mode 100644 index 0000000..4aeaf9f Binary files /dev/null and b/Measurement and analysis routines/AmplNoiseCal/GuiAmplNoiseCal.mlapp differ diff --git a/Measurement and analysis routines/AmplNoiseCal/MyAmplNoiseCal.m b/Measurement and analysis routines/AmplNoiseCal/MyAmplNoiseCal.m new file mode 100644 index 0000000..4e97cb4 --- /dev/null +++ b/Measurement and analysis routines/AmplNoiseCal/MyAmplNoiseCal.m @@ -0,0 +1,173 @@ +% Routine for the calibration of Relative Intensity Noise (RIN) spectrum +% using a calibration tone with known amplitude modulation depth, alpha, +% defined in the following expression for the complex amplitude: +% +% E_0(t) = A*(1+\alpha \cos(\Omega_{cal} t)) + +classdef MyAmplNoiseCal < MyAnalysisRoutine + + properties (Access = public, SetObservable = true) + + % Thermomechanical spectrum + Data MyTrace + + % RIN spectrum + AmplSpectrum MyTrace + + % Cursors for the selection of calibration tone + CalCursors MyCursor + cal_range = [0, 0] + + % Amplitude modulation depth of the calibration tone, supplied + % externally + alpha = 0.1 + end + + properties (GetAccess = public, SetAccess = protected, ... + SetObservable = true) + Axes + Gui + + % Frequency of the calibration tone, found in the cal_range + cal_freq + + % Conversion factor between S_V and RIN defined such that + % RIN = cf*S_V + cf = 1 + end + + methods (Access = public) + function this = MyAmplNoiseCal(varargin) + p = inputParser(); + addParameter(p, 'Data', MyTrace()); + addParameter(p, 'Axes', [], @isaxes); + addParameter(p, 'enable_gui', true, @islogical); + parse(p, varargin{:}); + + this.Data = p.Results.Data; + this.Axes = p.Results.Axes; + + this.AmplSpectrum = MyTrace(); + + if ~isempty(this.Axes) + + % Add two sets of vertical cursors for the selection of + % integration ranges + xlim = this.Axes.XLim; + x1 = xlim(1)+0.4*(xlim(2)-xlim(1)); + x2 = xlim(1)+0.45*(xlim(2)-xlim(1)); + + this.CalCursors = ... + [MyCursor(this.Axes, ... + 'orientation', 'vertical', 'position', x1, ... + 'Label','Cal 1', 'Color', [0, 0, 0.6]), ... + MyCursor(this.Axes, ... + 'orientation', 'vertical', 'position', x2, ... + 'Label','Cal 2', 'Color', [0, 0, 0.6])]; + end + + % Gui is created right before the construction of object + % is over + if p.Results.enable_gui + this.Gui = GuiAmplNoiseCal(this); + end + end + + function delete(this) + if ~isempty(this.CalCursors) + delete(this.CalCursors); + end + end + + % Calculates cf + function calcConvFactor(this) + if isempty(this.Data) || isDataEmpty(this.Data) + warning('Data is empty'); + return + end + + cr = this.cal_range; + + % Find the frequency of calibration tone + ind = (this.Data.x>cr(1) & this.Data.x<=cr(2)); + freq = sum(this.Data.x(ind) .* this.Data.y(ind))/ ... + sum(this.Data.y(ind)); + + this.cal_freq = freq; + + % Calculate area under the calibration tone peak + area = integrate(this.Data, cr(1), cr(2)); + + % Average square of relative intensity excursions due to the + % calibration tone + vSqCt = 2*this.alpha^2; + + this.cf = vSqCt/area; + end + + % Convert data using pre-calculated conversion factor + function convertSpectrum(this) + if isempty(this.Data) || isDataEmpty(this.Data) + warning('Data is empty'); + return + end + + this.AmplSpectrum.x = this.Data.x; + this.AmplSpectrum.y = this.Data.y*this.cf; + + this.AmplSpectrum.name_x = this.Data.name_x; + this.AmplSpectrum.unit_x = 'Hz'; + + this.AmplSpectrum.name_y = 'RIN'; + this.AmplSpectrum.unit_y = '1/Hz'; + + % Update metadata + this.AmplSpectrum.UserMetadata = createMetadata(this); + + triggerNewAnalysisTrace(this,'Trace',copy(this.AmplSpectrum)); + end + end + + methods (Access = protected) + function Mdt = createMetadata(this) + Mdt = MyMetadata('title', 'CalibrationParameters'); + + if ~isempty(this.Data.file_name) + + % If data file has name, indicate it + addParam(Mdt, 'source', this.Data.file_name, ... + 'comment', 'File containing raw data'); + end + + addParam(Mdt, 'alpha', this.alpha, ... + 'comment', 'Amplitude modulation depth'); + addParam(Mdt, 'cal_freq', this.cal_freq, ... + 'comment', ['Calibration tone frequency (' ... + this.Data.unit_x ')']); + addParam(Mdt, 'cf', this.cf, ... + 'comment', 'Conversion factor RIN = cf*S_V'); + end + end + + % Set and get methods + methods + + % Get the integration range for the calibration tone + function val = get.cal_range(this) + if ~isempty(this.CalCursors) && all(isvalid(this.CalCursors)) + + % If cursors exist, return the range between the + % cursors + xmin = min(this.CalCursors.value); + xmax = max(this.CalCursors.value); + + val = [xmin, xmax]; + else + + % Otherwise the value can be set programmatically + val = this.cal_range; + end + end + end +end +