NeurodataWithoutBorders / matnwb

A Matlab interface for reading and writing NWB files
BSD 2-Clause "Simplified" License
48 stars 32 forks source link

[Bug]: Unable to load nwb extensions in compiled MATLAB app. #564

Closed RR-N closed 3 weeks ago

RR-N commented 8 months ago

What happened?

I've implemented support for NWB files to a MATLAB application I'm developing. My code works fine, but when I try to load any NWB file after compiling the application, I get an error stating that the extension the NWB file in question relies upon (in this case ndx_multichannel_volume, which adds support for C. Elegans microscopy data) is inaccessible:

image

These are my compilation settings:

image

This seems to happen the moment any nwbRead() call that relies on an extension occurs, regardless of whether I include matnwb by passing it as a support package to mcc or by including it in the application path from the get-go.

It may also be worth noting that compilation also triggers two errors when this is first attempted:

  1. That lines 30 and 32 of +util/loadTimeSeriesData.m are invalid Matlab syntax. Checking the file shows that there are two colons used in IF statements on those lines, and removing those resolves this error.
  2. That the tutorial folder contains empty files that would cause errors. Deleting the tutorial folder resolves this error.

I couldn't find any recommended notes on how to include matnwb as a support package in a compiled Matlab app in the documentation, so if there's something I'm missing, please let me know.

Steps to Reproduce

1. Create Matlab application that utilizes nwbRead().
2. Create .prj file and compile said application with matnwb packaged.
3. Try to open NWB file that relies on extensions with compiled app.

Error Message

No response

Operating System

Windows

Matlab Version

-----------------------------------------------------------------------------------------------------
MATLAB Version: 23.2.0.2515942 (R2023b) Update 7
MATLAB License Number: 40702059
Operating System: Microsoft Windows 11 Home Version 10.0 (Build 22621)
Java Version: Java 1.8.0_202-b08 with Oracle Corporation Java HotSpot(TM) 64-Bit Server VM mixed mode
-----------------------------------------------------------------------------------------------------
MATLAB                                                Version 23.2        (R2023b)      License 40702059
Simulink                                              Version 23.2        (R2023b)      License 40702059
Bioinformatics Toolbox                                Version 23.2        (R2023b)      License 40702059
Computer Vision Toolbox                               Version 23.2        (R2023b)      License 40702059
Curve Fitting Toolbox                                 Version 23.2        (R2023b)      License 40702059
Deep Learning HDL Toolbox                             Version 23.2        (R2023b)      License 40702059
Deep Learning Toolbox                                 Version 23.2        (R2023b)      License 40702059
Global Optimization Toolbox                           Version 23.2        (R2023b)      License 40702059
Image Processing Toolbox                              Version 23.2        (R2023b)      License 40702059
MATLAB Coder                                          Version 23.2        (R2023b)      License 40702059
MATLAB Compiler                                       Version 23.2        (R2023b)      License 40702059
MATLAB Compiler SDK                                   Version 23.2        (R2023b)      License 40702059
Optimization Toolbox                                  Version 23.2        (R2023b)      License 40702059
Parallel Computing Toolbox                            Version 23.2        (R2023b)      License 40702059
Partial Differential Equation Toolbox                 Version 23.2        (R2023b)      License 40702059
Signal Processing Toolbox                             Version 23.2        (R2023b)      License 40702059
Statistics and Machine Learning Toolbox               Version 23.2        (R2023b)      License 40702059
System Identification Toolbox                         Version 23.2

Code of Conduct

RR-N commented 8 months ago

May be worth noting that I've replicated the issue on MacOS as well. All three errors mentioned pop on both systems.

rly commented 8 months ago

Pinging @lawrence-mbf

@RR-N It looks like when running the compiled app, the path to the extension might get messed up. What is the directory that you are running the compiled app from? Is it C:\Users\sep27\Documents\GitHub\NeuroPAL_ID\win_visualize\for_redistribution_files_only\NeuroPAL_ID_mcr?

RR-N commented 8 months ago

Pinging @lawrence-mbf

@RR-N It looks like when running the compiled app, the path to the extension might get messed up. What is the directory that you are running the compiled app from? Is it C:\Users\sep27\Documents\GitHub\NeuroPAL_ID\win_visualize\for_redistribution_files_only\NeuroPAL_ID_mcr?

The compiled app is run from C:\Users\sep27\Documents\GitHub\NeuroPAL_ID\win_visualize\for_redistribution_files_only\. And yeah, that's exactly what it looks like -- once compiled the extension seems to be searched for in ctfroot + the path to matnwb that was passed to the compiler.

lawrence-mbf commented 8 months ago

This probably has to do with the misc.getMatnwbDir() directory which may be baked into the compiler. If you call generateCore() from your compiled application, where are the files generated?

RR-N commented 8 months ago

This probably has to do with the misc.getMatnwbDir() directory which may be baked into the compiler. If you call generateCore() from your compiled application, where are the files generated?

Within the mcr folder in for_redistribution_files_only, so C:\Users\sep27\Documents\GitHub\NeuroPAL_ID\win_visualize\for_redistribution_files_only\NeuroPAL_ID_mcr\Users\sep27\AppData\Roaming\MathWorks\MATLAB Add-Ons\Collections\NeurodataWithoutBorders_matnwb(2):

image

lawrence-mbf commented 8 months ago

@RR-N It looks like by default (if you add the directory to "Files required for your application to run"), the working directory from misc.getMatnwbDir() should end up in %LOCALAPPDATA%\temp\<user>\mcrCachexx.x\<project name>\<matnwb dir>\

I wonder if you should use that instead of the -a option?

lawrence-mbf commented 8 months ago

@RR-N Ah, I think I know the issue actually. I do not believe the compiled mcr can actually fread externally generated matlab files. This is probably a security thing to prevent arbitrary execution (we do use eval for the purpose of accessing these generated class constructors).

lawrence-mbf commented 8 months ago

Also, the ".m" files are in fact p-coded so the mcr simply does not run ".m" source code and complains that it is "inaccessible".

I was also wrong on the fread part, it is just the mcr not being able to read MATLAB source code at all. You would need to pre-generate all the class files/extensions necessary before packaging the matnwb package.

MatNWB is heavily reliant on generated static MATLAB source files. Modifying the code to support this would be essentially rewriting the entire project.

RR-N commented 8 months ago

Pre-generating and adding an external reference to the extension within an isdeployed check worked for now -- I'll try a packaged solution next. I do still need to explicitly delete the colons in +util/loadTimeSeriesData.m and delete the tutorial folder to avoid errors during compilation though.

lawrence-mbf commented 8 months ago

If that is causing problems, you can just remove +util/loadTimeSeriesData.m afaik it is only used in tutorials which you have already deleted. None of which are required for nwbRead()

rly commented 8 months ago

That the tutorial folder contains empty files that would cause errors. Deleting the tutorial folder resolves this error.

Just curious since this seems strange. The repo does not have empty files in the root tutorials folder... Were the tutorial files modified or run and then generated empty files?

RR-N commented 6 months ago

That the tutorial folder contains empty files that would cause errors. Deleting the tutorial folder resolves this error.

Just curious since this seems strange. The repo does not have empty files in the root tutorials folder... Were the tutorial files modified or run and then generated empty files?

No, I didn't touch any of them prior to compilation.

ehennestad commented 3 weeks ago

It may also be worth noting that compilation also triggers two errors when this is first attempted: That lines 30 and 32 of +util/loadTimeSeriesData.m are invalid Matlab syntax. Checking the file shows that there are two colons used in IF statements on those lines, and removing those resolves this error.

This is now fixed in #609

ehennestad commented 3 weeks ago

I did some debugging on the following error:

That the tutorial folder contains empty files that would cause errors. Deleting the tutorial folder resolves this error.

This was related to the remote_read.mlx live script and seemed to happen because the live script did not have any MATLAB code blocks. I assume the compiler filters mlx files and "throws out" anything that is not code, and this is why the empty file error occurred.

I updated the live script (#610) and added a couple of code blocks (the live script happened to contain a few MATLAB expressions) and after that the compiler was happy.

@RR-N I hope the linked PR will solve the problems you encountered when compiling the app. I am closing this issue now, but feel free to re-open it if you run into more issues or have follow-up questions.