Create simulated experiment data sets

In this section of the exercise we show how to creat simulated experiment data sets. First of all, we set a reference time for our experiment. The t0 can be defined as follows.

clear all % Define a reference time for the experiments t0 = time('2012-01-17 17:04:11.529 UTC');

The two experiments are in fact two separate injections of frequency sweeps in the first and the differential channel. This means that we create a signal of sinusoidals and a signal of zeros for each experiment. These injections are already built-in and can be constructed with the equivalent input key of a plist.

Create first experiment (Inv0001) injection

For the injection signal to the first channel we can use the following:

%%% First channel (x1) % Create input signal from built-in model i1_1 = ao(plist('built-in', 'signals_3045_1_1')); % Adding reference time i1_1.setT0(t0);

We can call the zeropad function and add some zeros before and after the actual signal. These chuncks will be used to extract the simulated noise of the LTP system. The 'N' key of the plist defines the number of samples and with the 'position' key ('pre' or 'post') we can define where to add the zeros; before of after the built-in signal constructed.

% Add zeros before and after i1_1.zeropad(plist('N', 200000, 'position', 'pre')); i1_1.zeropad(plist('N', 20000, 'position', 'post')); % Set Name i1_1.setName('Inv0001_x1_inj');

The input of zeros to inject to the differential channel is easier to obtain. We construct an ao object with an input plist. The 'Yvals' would be all zeros and the number of samples the same as inj_1_1.

%%% Second channel (x12) % Input signal for second channel is zero % We build this signal by forcing it to lay on the same time values as the i1_1 i1_2 = ao(plist('Yvals', zeros(size(i1_1.x)), 'fs', 10, 't0', t0, 'Yunits', 'm')); i1_2.setToffset(i1_1.toffset); i1_2.setName('Inv0001_x12_inj');

Plotting the injection for the two channels in the first experiment produces the figure below.

% Plot injection signals iplot(i1_1, i1_2)

Create second experiment (Inv0002) injection

The same would apply for the second experiment with the exception that:

  1. The injection is applied now to the second channel.
  2. The injected signal is different from the previous. We use the built-in signa signals_3045_1_1.

%% Generate data for experiments Inv0002 %%% Second channel i2_2 = ao(plist('built-in','signals_3045_1_2')); i2_2.setT0(t0); i2_2.zeropad(plist('N', 200000,'position', 'pre')); i2_2.zeropad(plist('N', 20000,'position', 'post')); i2_2.setName('Inv0002_x1_inj'); %%% First channel i2_1 = ao(plist('Yvals', zeros(size(i2_2.x)), 'fs', 10, 't0', t0)); i2_1.setToffset(i2_2.toffset); i2_1.setName('Inv0002_x12_inj'); iplot(i2_1, i2_2)

Create the model for data generation

To generate our data sets we will use the built-in model LPF which assemble in a single object all the subsystems together with a default profile of noise inputs. For more information on the model type

help ssm_model_LPF

We will build this model at the same time that we set some parameters to a certain numerical value. These are the parameters that we will be estimating in later in this exercise and are described in the following table

Key Value Description



FEEPs actuation gain in X direction



Capacitive actuation in TM2 in X direction



Interferometer cross-coupling X1 -> X12



TM1 stifness in X direction (squared)



TM2 stifness in X direction (squared)

On our implementation, we first define a string params with the name of the parameters, an array values with the numerical values previously defined and then we input them to the plist that defines our model.

% Define parameters and nominal values params = {... 'FEEPS_XX', ... % Coupling of the commanded force along X to the applied force along X 'CAPACT_TM2_XX', ... % Actuaction cross-coupling of TM2 force along X to TM2 force along X 'IFO_X12X1', ... % The coupling of the x position of TM1 to the estimated x position of TM2 w.r.t. TM1 'EOM_TM1_STIFF_XX', ... % Total stiffness of TM1 along X when moving along X. 'EOM_TM2_STIFF_XX' ... % Total stiffness of TM2 along X when moving along X. }; values = [0.82 1.08 0.0004 1.3e-6 1.9e-6]; % Create plist defining how we want to build the model simPlist = plist('built-in','LPF', ... % From built-in models 'DIM', 1, ... % We use a one dimensional model 'CONTINUOUS', false, ... % The model descrete 'param names', params, ... % Parameter names 'param values', values, ... % Parameter values 'VERSION', 'Best Case June 2011'); % Version of the LPF % Create the LPF model. LPF = ssm(simPlist); %% save model save(LPF, 'generation_LPF_model.mat');

Generate data for the experiments

To produce a set of data we first need to define how the different noise sources are correlated, i.e. the noise covariance. The ssm class provides a method that provides this information (although the user is free to provide his own covariance matrix)

%% Generate noise covariance for experiments 1 & 2 cov = LPF.generateCovariance;

Next, define the ports where the inputs are injected abd where the outputs are measured

% Define input and output channels inNames = {... 'GUIDANCE.IFO_x1' ... % x1 control coordinate, read by o1 IFO 'GUIDANCE.IFO_x12' ... % x12 control coordinate, read by differential IFO }; outNames = {... 'DELAY_IFO.x1' ... % o1 IFO 'DELAY_IFO.x12' ... % o12 IFO 'DFACS.sc_x' ... % commanded force on SC 'DFACS.tm2_x' ... % commanded force on TM2 };

And add this information in a plist and use it to call the method simulate

pl_sim_Inv0001 = plist(... 'aos variable names', inNames(1),... 'aos', i1_1,... 'return outputs', outNames,... 'cpsd variable names', cov.find('names'), ... 'cpsd', cov.find('cov'), ... 'displayTime', true,... 't0', t0); % Inv0001: run the simulation % In this investigation, the guidance is applied on the x1 control coordinate, read by o1 IFO pl_sim_Inv0001 = plist(... 'aos variable names', inNames(1),... % Names of the inputs 'aos', i1_1,... % injection signals 'return outputs', outNames,... % Names of the outputs 'cpsd variable names', cov.find('names'), ... 'cpsd', cov.find('cov'), ... 'displayTime', true,... 't0', t0); % Generate data o_0001 = LPF.simulate(pl_sim_Inv0001);

We unpack to recover all the different output ports we ask for in the plist

% The output Analysis Objects are grouped in a matrix object, so we need to index them [o1_0001, o12_0001, Fsc_0001, Ftm2_0001] = o_0001.unpack;

And repeat the same operation to produce the data set for the second experiment. Notice that in the plist we change the input port (in order to inject the signal in the differential channel) and the injected signal is now i2_2

% Inv0002: run the simulation % In this investigation, the guidance is applied on the x12 control coordinate, read by differential IFO pl_sim_Inv0002 = plist(... 'aos variable names', inNames(2), ... 'aos', i2_2, ... 'return outputs', outNames, ... 'cpsd variable names', cov.find('names'), ... 'cpsd', cov.find('cov'), ... 'displayTime', true, ... 't0', t0); % Generate data o_0002 = LPF.simulate(pl_sim_Inv0002); % The output Analysis Objects are grouped in a matrix object, so we need to unpack them [o1_0002, o12_0002, Fsc_0002, Ftm2_0002] = o_0002.unpack;

Build matrix objects for the analysis

The methods that we will use in the analysis work, for simplicity, with matrix objects. These objects allow to put several time series together to refelct the fact that our analysis requires many channels. In this particular case only two: x1 and x12. The objects are built as follows:

%% Build matrix objects % Group the guidance injection signals of both experiments in the same matrix model inj_signal(1) = matrix(i1_1, i1_2, plist('shape', [2 1])); inj_signal(2) = matrix(i2_1, i2_2, plist('shape', [2 1])); % Group the measured outputs of both experiments in the same matrix model meas_signal(1) = matrix(o1_0001, o12_0001, plist('shape', [2 1])); meas_signal(2) = matrix(o1_0002, o12_0002, plist('shape', [2 1])); % Group the commanded forces of both experiments in the same matrix model cmd_forces(1) = matrix(Fsc_0001, Ftm2_0001, plist('shape', [2 1])); cmd_forces(2) = matrix(Fsc_0002, Ftm2_0002, plist('shape', [2 1]));

Once these objects are built, we can easily split our original data into the different segments of interest: we take a short segment where the input was applied for the in and out object, and a long segment without injected signal for the noise.

% Split in times to get input, output, noise and commanded forces chunks in = split(inj_signal, plist('times', [-2000 inf])); out = split(meas_signal, plist('times', [-2000 inf])); noise = split(meas_signal, plist('times', [-inf -2000])); Fcmd = split(cmd_forces, plist('times', [-inf -2000]));

Each of these contains two matrix objects (one for each experiment), with two time series (for x1 and x12) within. We can take a look at the objects for the second experiment:

% Plot injected signal in 2nd experiment in(2).iplot
% Plot measured signal in 2nd experiment out(2).iplot
% Plot initial noise segment in 2nd experiment noise(2).iplot
% Plot commanded forces in 2nd experiment Fcmd(2).iplot

Finally, we just need to save the objects we have just created. We will use them later for parameter estimation.

%% save objects save([o_0001 o_0002], 'full_signal.mat'); save(inj_signal, 'inj_signal.mat'); save(in, 'input.mat'); save(out, 'output.mat'); save(noise, 'noise.mat'); save(Fcmd, 'cmdForces.mat');

©LTP Team