# Running COSMOSS from the workspace
In this tutorial, I will layout a step-by-step process about how to run COSMOSS from workspace (command line mode). One of the major benefits is to run it in a batch mode. Running in batch mode allows one to explore the "change" from some acting variables. For example, given two molecules, if you want to know how would spectral features change when you pull them away, you can run simulations in a for-loop instead of laborious mouse-clickings. Even better is that you can visualize the result as a movie!
:::info
Objective:
Generating the movie of FTIR spectral change while pulling two molecules away from 3 to 7<span>Å</span>.
:::

## Constructing the TCO model
:::warning
Before we start, make sure you've already run COSMOSS at least once so all the paths to relevant function are set!
This tutorial works for version v2.3.2 and newer, so update your COSMOSS before start.
:::
To generate a structure model, COSMOSS call the **model constructors** when you click on the **Generate** button from the Model_GUIs. In this example, we are constructing the classic TCO model and the corresponding constructor function is defined in the 'ConstructTCO.m' in the following path:
```
.../MoleculeConstruction/TCO/
```
Side note: To figure out what exactly the **Generate** button of the 'Model_TCO' is doing, Let's dig into the **Button_GeneratePushed** function of the 'Model_TCO.mlapp':

:::warning
To view/edit the GUIs, please see the tutorial on [How to edit COSMOSS GUIs](/Vy7kwQ4WTHGCOLoZqNPhnw).
:::
Here is the first few lines of the **ConstructTCO.m**:

To construct a TCO model, one needs to provide *one* input argument only: **GUI_Inputs**. The GUI_Inputs is a [Matlab structure array](https://www.mathworks.com/help/matlab/ref/struct.html) collecting a bunch of name/value pairs (don't be confused, the *structure* array has nothing to do with the 3D *structure* we are constructing here!).
Note that there is an **Input Parser** section determines if the required inputs( in this case, the **fields** of the **GUI_Inputs** ) were provided. If a required field were missing, a default value will be assigned to the **GUI_Inputs** so all the necessary fields will be ready before running any meaningful codes below. For example, if the *Displacement* field is missing in the *GUI_Inputs*, the *defaultDisplacement* will be assigned to the *GUI_Inputs* so that
```
>> GUI_Inputs.Displacement
ans =
0 0 5
```
:::warning
One more important remark about the **Input parser** section:
Almost every functions in COSMOSS have an **Input parser** section. The list of the Inputs fields give you an idea about what are possible parameters one can safely play around. The section acts sort of like an [Application Programming Interface](https://en.wikipedia.org/wiki/Application_programming_interface). And it is useful for debugging without figuring out what are necessary variables to run an interested code.
:::
In this example, I want to place the two molecule at 3<span>Å</span> away on the X axis. I also want to tilt each of them 30 degrees away from the Z axis, in opposite directions, so that the FTIR peaks split (i.e. 2 peaks!). To define such orientation, I can construct an empty structure array, named **GUI_Inputs** and fill-in all the necessary fields:
```
GUI_Inputs = struct;
GUI_Inputs.Displacement = [3,0,0];
GUI_Inputs.Theta_D1 = -30;
GUI_Inputs.Theta_D2 = 30;
```
Running the **ConstructTCO** function with the prepared 'GUI_Inputs' will results in a [StructureData Class](/_pCi32hpSFm-r1Or4bxVnA), here I named SD_TCO.
```
SD_TCO = ConstructTCO(GUI_Inputs);
```
One can verify the generated structure with the **SD_Draw** method:
```
SD_TCO.SD_Draw;
```

## Simulate the FTIR spectra
Now we have a model structure (SD_TCO), let's take a look at the Main_GUI to see what will happen if I click on the **FTIR** button?
```
>> appdesigner COSMOSS
```

The first thing it does is use the **CheckStructue()** function to see if a model structure exist in the main GUI:

The following 4 lines deal with other GUI related works (i.e. not important for our purpose):
```
app.RefreshSource = 'FTIR'; % Identify source if trigger
RefreshOff(app) % Turn off the auto-refresh tag for FTIR
% Switch the experimental setting panel on the Main_GUI to 1D tab
app.TabGroup.SelectedTab = app.DTab_Exp1D;
app.TabGroupTools.SelectedTab = app.Tab_FTIR;
```
:::warning
Note: all of the above are not relevant to run simulation in the command line mode. Don't worry if you don't understand.
:::
The only relevant code is this one:
```
app.Data_FTIR = OneD_Iteration(@FTIR_Main,app);
```
This line assigns the output of the **OneD_Iteration** function as the Data_FTIR field in the Main_GUI. The input of the **OneD_Iteration** function takes the [function handle](https://www.mathworks.com/help/matlab/function-handles.html) of FTIR simulation code, named **@FTIR_Main** and pass the GUI related data by the variable **app**
The **OneD_Iteration** function deals with the ensemble average of the one-dimensional spectrum( i.e. FTIR and SFG ), which will be detailed in another tutorials. Here we only care about what it does without the ensemble average:
```
function OneD = OneD_Iteration(h1DFunc,app)
I = app.Parse_GUI;
S = app.Structure;
...
if eq(I.Sampling,1)
...
% Codes deal with the ensemble average, which we neglect.%
...
else
OneD = h1DFunc(S,I); % call the 1D spectral simulation function
Plot1D(hAx,OneD,I); % draw the spectra
end
```
What **OneD_Iteration** really does is call the simulation function **FTIR_Main** and providing two inputs: **S**(Model structure) and **I** (GUI inputs on the Main_GUI) for the **FTIR_Main**.
Since there is another **Input parser** section in the Main_GUI taking care of the default inputs (see 'Parse_GUI()' function in the [COSMOSS.mlapp](/Vy7kwQ4WTHGCOLoZqNPhnw) file for details), and we just generated the TCO model (SD_TCO), we can simply run the code as follow:
```
OneD = FTIR_Main(SD_TCO,GUI_Inputs);
```
The output variable **OneD** contains information for drawing the spectra. We just need to provide a handle of a figure axes for the **Plot1D** to work:
```
hF = figure;
hAx_FTIR = axes('Parent',hF);
Plot1D(hAx_FTIR,OneD,GUI_Inputs);
```
Voila, here is your FTIR spectra!
Wait... But, it doesn't looks quite right since I am expecting two peaks...

Seems like my x range may not be correct. Let's check what are the possible inputs in the **Plot1D** function to correct this error:

Let's change the default vales by adding the 'FreqRange' field to the GUI_Input and regenerate the SD_TCO. Here is the code puts everything together:
```
GUI_Inputs = struct;
GUI_Inputs.Theta_D1 = -30;
GUI_Inputs.Theta_D2 = 30;
GUI_Inputs.FreqRange = 1650:1800;
SD_TCO = ConstructTCO(GUI_Inputs);
hF = figure;
hAx_FTIR = axes('Parent',hF);
Plot1D(hAx_FTIR,OneD,GUI_Inputs);
```
Finally, here is the correct spectra!!!

:::warning
You may wonder where is the local mode frequency defined?
Hint: Try to read the **ConstructTCO.m** and you will find it calls **SD_1ExH()** function to generate the one-exciton Hamiltonian of the system. You might want to check the input parser section 😁.
:::
## Scanning the distance
With previous sections, we know how to simulate a FTIR spectra for the model TCO at a specific configuration. In order to make a movie of FTIR spectral change when the two molecules pulling apart, we need to simulate all the configurations and save them as movie frames.
Let's prepare an array (distanceArray) and run a for-loop by substituting the X distance between the two molecules for the simulations. Also, we will need to provide some figure/axes setting so the molecule structure and the corresponding FTIR spectra will be presented side-by-side. Finally, the figures will be saved as an array of movies frames (Frame_all) waiting for further inspection.
```
%% Setup scanning parameters
distanceArray = 3:0.1:7;
GUI_Inputs = struct;
GUI_Inputs.Theta_D1 = -30;
GUI_Inputs.Theta_D2 = 30;
GUI_Inputs.FreqRange = 1650:1800;
% figure setting
hF = figure;
hF.Position = [100,100,800,300];
hAx_FTIR = subplot(1,2,1,'Parent',hF);
hAx_Molecule = subplot(1,2,2,'Parent',hF);
%% Structure generation, simulation, and make figure
for i = 1:length(distanceArray)
% clear the axises before start
cla(hAx_FTIR)
cla(hAx_Molecule)
% Prepare initial structure
GUI_Inputs.Displacement = [distanceArray(i),0,0];
SD_TCO = ConstructTCO(GUI_Inputs);
% Run the Spectral simulation
OneD = FTIR_Main(SD_TCO,GUI_Inputs);
% make figure
Plot1D(hAx_FTIR,OneD,GUI_Inputs);
SD_Draw(SD_TCO,hAx_Molecule);
hAx_Molecule.XLim = [-6,6];
drawnow % force to update figure before the for-loop is finished
Frame_all(i) = getframe(hF);
end
```
## Generating the GIF
Now we are ready to play back the movie frames by generate the same figure settings:
```
%% Play movie frames
hF = figure;
hF.Position = [100,100,800,300];
hAx_FTIR = subplot(1,2,1,'Parent',hF);
hAx_Molecule = subplot(1,2,2,'Parent',hF);
movie(hF,Frame_all,10) % play the movie for 10 times
```
Voila! The movie succesully capture the two extreme from strongly coupled case with two distictive peaks to nearly non-coupled case where the two peaks merge as one.

To save the movie as a GIF, we need to convert the movie frames to images (frame2im & rgb2ind)and write it as a image sequence. Here I provide an example code for it:
```
%% Save GIF
saveGIF = 1;
BaseFileName = 'TCO_X3_X10';
SavePath = '~/Desktop';
SaveName = [SavePath,'/',BaseFileName,'.gif'];
DT = 0.1;
if saveGIF
for j = 1:length(distanceArray)
frame = Frame_all(j);
im = frame2im(frame);
[imind,cm] = rgb2ind(im,256);
if j == 1
imwrite(imind,cm,SaveName,'gif','Loopcount',inf,'DelayTime',DT);
else
imwrite(imind,cm,SaveName,'gif','WriteMode','append','DelayTime',DT);
end
end
disp([BaseFileName, 'GIF saved...'])
end
```
## The flow chart of the code
:::warning
Final remark: The same workflow can be easily adapt for different purposes. Once you understand how to find the necessary parameters for an interested function, you can call the function through the workspace how ever you like. This is an essential ability for testing/debugging COSMOSS.
:::
```flow
st=>start: start
e=>end: Save GIF
op1=>operation: Set initial parameters
op2=>operation: Modify model
op3=>operation: Simulate spectrum
cond=>condition: Finished?
st->op1->op2->op3->cond
cond(yes)->e
cond(no)->op2
```
## The full example code
Here is the code after we put everything together (tested and run after version v2.3.2):
```
%% Setup canning parameters
distanceArray = 3:0.1:7;
GUI_Inputs = struct;
GUI_Inputs.Theta_D1 = -30;
GUI_Inputs.Theta_D2 = 30;
GUI_Inputs.FreqRange = 1650:1800;
% figure setting
hF = figure;
hF.Position = [100,100,800,300];
hAx_FTIR = subplot(1,2,1,'Parent',hF);
hAx_Molecule = subplot(1,2,2,'Parent',hF);
%% Strueture generation, simulation, and make figure
for i = 1:length(distanceArray)
% clear the axises before start
cla(hAx_FTIR)
cla(hAx_Molecule)
% Prepare initial structure
GUI_Inputs.Displacement = [distanceArray(i),0,0];
SD_TCO = ConstructTCO(GUI_Inputs);
% Run the Spectral simulation
OneD = FTIR_Main(SD_TCO,GUI_Inputs);
% make figure
Plot1D(hAx_FTIR,OneD,GUI_Inputs);
SD_Draw(SD_TCO,hAx_Molecule);
hAx_Molecule.XLim = [-6,6];
drawnow
Frame_all(i) = getframe(hF);
end
%% Save GIF
saveGIF = 1;
BaseFileName = 'TCO_X3_X10';
SavePath = '~/Desktop';
SaveName = [SavePath,'/',BaseFileName,'.gif'];
DT = 0.1;
if saveGIF
for j = 1:length(distanceArray)
frame = Frame_all(j);
im = frame2im(frame);
[imind,cm] = rgb2ind(im,256);
if j == 1
imwrite(imind,cm,SaveName,'gif','Loopcount',inf,'DelayTime',DT);
else
imwrite(imind,cm,SaveName,'gif','WriteMode','append','DelayTime',DT);
end
end
disp([BaseFileName, 'GIF saved...'])
end
%% Play movie frames
hF = figure;
hF.Position = [100,100,800,300];
hAx_FTIR = subplot(1,2,1,'Parent',hF);
hAx_Molecule = subplot(1,2,2,'Parent',hF);
movie(hF,Frame_all,10)
```
###### tags:`tutorials` `COSMOSS`