Skip to content

Commit

Permalink
Merge pull request #2282 from fernweh-3/cobrarrow
Browse files Browse the repository at this point in the history
Add initCobrarrow, Fix MATLAB Version Compatibility, Update Documentation
  • Loading branch information
rmtfleming authored Aug 30, 2024
2 parents 238a9c4 + 67f6a17 commit 1dbf9df
Show file tree
Hide file tree
Showing 3 changed files with 96 additions and 114 deletions.
14 changes: 7 additions & 7 deletions src/cobrarrow/COBRArrow.m
Original file line number Diff line number Diff line change
Expand Up @@ -500,9 +500,9 @@ function sendField(obj, schemaName, fieldName, fieldData, toOverwrite)

% Convert specific fields in the struct to appropriate MATLAB types
resultStruct.rxns = cellfun(@char, cell(tempStruct.rxns), 'UniformOutput', false)';
resultStruct.flux = double(tempStruct.flux)';
resultStruct.flux = cellfun(@double, cell(tempStruct.flux))';
resultStruct.status = char(tempStruct.status);
resultStruct.objective_value = double(tempStruct.objective_value);
resultStruct.objective_value = cellfun(@double, cell(tempStruct.objective_value));
end

function persistModel(obj, schemaName, toOverwrite)
Expand Down Expand Up @@ -1065,7 +1065,7 @@ function loadFromDuckDB(obj,schemaName)
columnData = pyArrowTable.columns{1}.to_pylist();

% Convert the Python list to a MATLAB double array
data = double(columnData);
data = cellfun(@double, cell(columnData));

% Transpose the double array to match the expected MATLAB format
fieldData = data';
Expand Down Expand Up @@ -1139,9 +1139,9 @@ function loadFromDuckDB(obj,schemaName)
ncols = dimensionsArray(2);

% Extract row, column, and value data from the PyArrow table
row = double(pyArrowTable.columns{1}.to_pylist());
col = double(pyArrowTable.columns{2}.to_pylist());
val = double(pyArrowTable.columns{3}.to_pylist());
row = cellfun(@double, cell(pyArrowTable.columns{1}.to_pylist()));
col = cellfun(@double, cell(pyArrowTable.columns{2}.to_pylist()));
val = cellfun(@double, cell(pyArrowTable.columns{3}.to_pylist()));

% Construct a sparse matrix from the row, column, and value data
fieldData = sparse(row, col, val, nrows, ncols);
Expand Down Expand Up @@ -1236,7 +1236,7 @@ function loadFromDuckDB(obj,schemaName)
columnData = pyArrowTable.columns{1}.to_pylist();

% Convert the Python list to a MATLAB int64 array
data = int64(columnData);
data = cellfun(@int64, cell(columnData));
% Transpose the integer array to match the expected MATLAB format
fieldData = data';
end
Expand Down
137 changes: 30 additions & 107 deletions src/cobrarrow/README.md
Original file line number Diff line number Diff line change
@@ -1,154 +1,77 @@
# Instructions for Using MATLAB API

This guide will walk you through setting up and running the MATLAB API.
## Step 1: Run `initCobrarrow`

## Step 1: Install Python and Create a Virtual Environment
1. In the MATLAB command window, run the following command:

If Python is not installed on your system, download and install a compatible version as specified by [MathWorks](https://www.mathworks.com/content/dam/mathworks/mathworks-dot-com/support/sysreq/files/python-support.pdf).
```matlab
initCobrarrow()
```
2. If you encounter an error while running `initCobrarrow`, it may be because Python is not installed on your system or the installed version is not compatible with MATLAB.
### 1.1 Create a Virtual Environment
- **Solution**: Download and install a compatible version of Python as specified by [MathWorks Python Compatibility](https://www.mathworks.com/content/dam/mathworks/mathworks-dot-com/support/sysreq/files/python-support.pdf).
- For detailed instructions on installing and configuring Python, refer to the following MathWorks documentation:
- [Configure Your System to Use Python](https://uk.mathworks.com/help/matlab/matlab_external/install-supported-python-implementation.html)
Ensure you use a Python version compatible with your MATLAB installation. For this example, we'll use Python 3.9.
```sh
# Specify Python version when you create the virtual environment
python3.9 -m venv python_env
```

### 1.2 Activate the Virtual Environment

Activate the virtual environment you just created:

- **On Windows:**

```sh
.\python_env\Scripts\activate
```

- **On macOS and Linux:**

```sh
source python_env/bin/activate
```

## Step 2: Install Dependencies

Once the virtual environment is activated, install the required dependencies using the `requirements.txt` file provided with the MATLAB API:

```sh
pip install -r requirements.txt
```

## Step 3: Set MATLAB to Use the Python Environment

To ensure MATLAB uses this Python environment every time it starts:

1. **Locate or Create the MATLAB Startup File**:

- On Windows: The `startup.m` file is usually located in the `Documents\MATLAB` folder.
- On macOS or Linux: The file is also named `startup.m` and is located in the MATLAB user folder, typically `~/Documents/MATLAB`.

If the file doesn't exist, create a new `startup.m` file in the appropriate directory.
2. **Edit the Startup File**:

Add the following lines to the `startup.m` file, replacing the path with the full path to your virtual environment's Python executable:

```matlab
% Set the Python environment for MATLAB
pyenv('Version', fullfile('path_to_your_virtual_env', 'python'));
```

For example:

```matlab
pyenv('Version', fullfile('C:\COBRArrow\client\MATLAB_API\python_env\Scripts\python.exe'));
```

Or on macOS/Linux:

```matlab
pyenv('Version', fullfile('~/Document/COBRArrow/client/MATLAB_API/python_env/bin/python'));
```

3. **Save and Restart MATLAB**:

Save the `startup.m` file. When you restart MATLAB, it will automatically use the specified Python environment.


## Step 4: MATLAB API is ready to use.
## Step 2: MATLAB API is ready to use.
### Example Use of Calling MATLAB APIs
Refer to MATLAB script `testMatlab.m` that uses the MATLAB API to perform some operations.

```matlab
% Example MATLAB script to use the MATLAB API
% load the model
recon3D_model = load('../models/Recon3D_301.mat').Recon3D;
model = recon3D_model;
schemaName = 'Recon3D';
% Load the model
file = load('path/to/your_model.mat');
model = file.yourModel;
schemaName = 'yourModelName';
% Create an instance of the COBRArrow class
host = 'localhost';
port = 443;
host = 'cobrarrowServerHost';
port = cobrarrowServerPort; % port is optional if you use a domain name for host
client = COBRArrow(host, port);
% Login
client = client.login('johndoe', '123456');
client = client.login('username', 'password');
% Send the model to the server
client.sendModel(model, schemaName);
% Persist the model in DuckDB
client.persistModel(schemaName, true);
% Read the model back for general purposes
fetchedModel = client.fetchModel(schemaName);
disp('Fetched Model:');
disp(fetchedModel);
% For example, fetchedModel can be used to do simulations using COBRA Toolbox
initCobraToolbox;
solution = optimizeCbModel(fetchedModel);
disp('solution:');
disp(solution);
% Read the model back for FBA analysis
FBAmodel = client.fetchModelForFBAAnalysis(schemaName);
disp('FBA Model:');
disp(FBAmodel);
% Set solver for using remote optimization service
arrowSolver = COBRArrowSolver('GLPK');
arrowSolver.setParameter('tol', 1e-9);
% Perform optimization
resultStruct = client.optimizeModel(schemaName,arrowSolver);
% Display results
disp('Optimization Results:');
disp(resultStruct);
% Perform optimization
resultStruct = client.optimizeModel(schemaName, arrowSolver);
% Example of sending an individual field
fieldName = 'rxns';
fieldData = model.rxns;
% Example of sending flux value(an individual field) for animation
fieldName = 'flux';
fieldData = resultStruct.flux;
client.sendField(schemaName, fieldName, fieldData);
% Read the field back
readData = client.readField(schemaName, fieldName);
disp('Read Field Data:');
disp(readData);
readData = client.fetchField(schemaName, fieldName);
% List all flight information in a schema on server
% List all flight information in a schema on the server
flightsList = client.listAllFlights(schemaName);
disp('Flights List in schema:');
disp(flightsList);
% List all flight information on server
% List all flight information on the server
flightsList = client.listAllFlights();
disp('All Flights List:');
disp(flightsList);
% Get all unique identifier of the flights in a schema
% Get all unique identifiers of the flights in a schema
descriptors = client.getAllDescriptors(schemaName);
disp('Descriptors:');
disp(descriptors);
```
59 changes: 59 additions & 0 deletions src/cobrarrow/initCobrarrow.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
function initCobrarrow()
% Display MATLAB version
ver = version;
fprintf('MATLAB Version: %s\n', ver);

% Check if Python is installed and display details
pyEnvInfo = pyenv;

if isempty(pyEnvInfo.Executable)
showInstruction();
else
fprintf('Python is installed. Version: ');
disp(pyEnvInfo.Version);
fprintf('Python Executable: \n');
disp(pyEnvInfo.Executable);

% test Python version compatibility
try
py.math.sqrt(16);
catch ME
showInstruction();
rethrow(ME);
end

% Get the current directory where the MATLAB script is located
currentFile = mfilename('fullpath');
currentDir = fileparts(currentFile);

% Construct the full path to the requirements.txt file
requirementsPath = fullfile(currentDir, 'requirements.txt');

% Use python -m pip install to ensure pip is invoked correctly
cmd = sprintf('"%s" -m pip install -r "%s"', pyEnvInfo.Executable, requirementsPath);
status = system(cmd);

if status == 0
% test if pyarrow package works
py.pyarrow.table(py.dict(pyargs('column1', {1, 2, 3, 4})));
disp('Python package pyarrow installed successfully.');
else
error('Failed to install packages.');
end

fprintf("\nNow you can use the COBRArrow API in MATLAB.\n\n");

end
end

function showInstruction()
versionLink = 'https://uk.mathworks.com/support/requirements/python-compatibility.html?s_tid=srchtitle_site_search_1_python%20compatibility';
versionLabel = 'Versions of Python Compatible with MATLAB';
configLink = 'https://uk.mathworks.com/help/matlab/matlab_external/install-supported-python-implementation.html';
configLabel = 'Configure Your System to Use Python';

fprintf('Python is not installed or not set up in MATLAB.\n');
fprintf('Please install the correct version of Python according to ');
fprintf('<a href="%s">%s</a>. \n', versionLink, versionLabel);
fprintf('Please refer to <a href="%s">%s</a> to config Python in MATLAB. \n', configLink,configLabel);
end

0 comments on commit 1dbf9df

Please sign in to comment.