Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Module not found error with scripting #60

Open
BonnieAlexander opened this issue Nov 29, 2023 · 6 comments
Open

Module not found error with scripting #60

BonnieAlexander opened this issue Nov 29, 2023 · 6 comments

Comments

@BonnieAlexander
Copy link

Hi,

Thank you for your software!

We are trying to update to MRIcroGL_QT (MRIcroGL 1.2.20220720c QT5 x86-64 LLVM) since updating to Ubuntu version:
Release 22.04.3 LTS (Jammy Jellyfish) 64-bit
Kernel Linux 6.2.0-37-generic x86_64
MATE 1.26.0

MRIcroGL_QT itself opens and works great, but running a python script for screenshots isn't working. The error in shown in the scripting part via the GUI is:

Running Python script
Traceback (most recent call last): File "", line 12, in ModuleNotFoundError: No module named 'glob'
Python Successfully Executed

Any suggestions would be much appreciated.

Thanks very much,

Bonnie.

@neurolabusc
Copy link
Contributor

Are your sure your script is running the "gl" module, not "glob"? I am unable to replicate your problem on Ubuntu 23.10: the savebmp function works fine for me. I ran this script:

import gl
gl.resetdefaults()
#open background image
gl.loadimage('spm152')
#open overlay: show positive regions
gl.overlayload('spmMotor')
gl.minmax(1, 4, 4)
gl.opacity(1,50)
#open overlay: show negative regions
gl.overlayload('spmMotor')
gl.minmax(2, -4, -4)
gl.colorname (2,"3blue")
gl.mosaic("A L+ H -0.2 -24 -16 16 40; 48 56 S X R 0");
gl.savebmp('mytest.png')

mytest

The Help/About menu item reports:

MRIcroGL 1.2.20220720c QT5 x86-64 LLVM
Author: Chris Rorden
License: BSD 2-Clause
Linux
NVIDIA Corporation; OpenGL= 4.6.0 NVIDIA 535.129.03; Shader=4.60 NVIDIA
2.1 Max 3D texture: 16384
Current texture: 207×256×215 43mb

And the command line reports:

$ lsb_release -a
No LSB modules are available.
Distributor ID:	Ubuntu
Description:	Ubuntu 23.10
Release:	23.10
Codename:	mantic
$ uname -a
Linux ryzen 6.5.0-13-generic #13-Ubuntu SMP PREEMPT_DYNAMIC Fri Nov  3 12:16:05 UTC 2023 x86_64 x86_64 x86_64 GNU/Linux

@BonnieAlexander
Copy link
Author

BonnieAlexander commented Nov 29, 2023

Hi,

Thanks for your quick reply. Here is a generic example of a script we might use, which works fine for MRIcroGL_QT (MRIcroGL 1.2.20210317 QT5 x86-64 LLVM) on Ubuntu version:
20.04.6 LTS (Focal Fossa) 64-bit
Kernel Linux 5.15.0-88-generic x86_64

import gl
import os
import sys
import glob

brain_azimuth = 295
brain_elevation = 155
intensity_window_min = 40
intensity_window_max = 300

display_scripts_directory = os.getcwd()
main_display_directory = os.path.dirname(display_scripts_directory)

output_screenshots_directory = os.path.join(main_display_directory, 'T1_screenshots')

if not os.path.isdir(output_screenshots_directory):
     os.mkdir(output_screenshots_directory)

imagelist = glob.glob(os.path.join(main_display_directory, 'nifti', '*T1*'))
imagelist.sort(reverse = True)

for n,i in enumerate(imagelist):
     gl.resetdefaults()
     layer_number = 0 
     print(i)   
     gl.loadimage(i)
     gl.minmax(layer_number, intensity_window_min, intensity_window_max)  

     for x in [[brain_azimuth, brain_elevation]]:
        gl.azimuthelevation(x[0], x[1])
        gl.wait(200)
        gl.savebmp(os.path.join(output_screenshots_directory, 'T1_screenshot.png'))

gl.quit()

Thanks,

Bonnie.

@neurolabusc
Copy link
Contributor

Bonnie,
MRIcroGL uses its own standalone version of Python (in the /Resources/python37 folder rather than the system Python. This means it does not have access to the same installation of Python as you get from the command line. This is required by many distributions (like MacOS) which see access to the system Python by a graphical application as a vulnerability. In theory, you can recompile MRIcroGL with the PYTHON_DYNAMIC compiler directive to use the system's dynamic Python library rather than the static library. This feature is also outlined in the Debian build:

lazbuild  -B MRIcroGL_Debian.lpi

I have not tried this in years, so your mileage may vary.

Alternatively, I recommend the method suggested in the manual where you run a Python script from the command line using the Python of your current environment (with all its packages). Here is an example script that finds all the scans of a specific modality from a BIDS dataset and generates a bitmap image to ensure successful defacing:

#!/usr/bin/python

# Create bitmaps to check defacing of all NIFTI images
#  python bids_deface_bitmaps.py

from pathlib import Path
import os
import os.path
import glob
import sys
import shutil

if __name__ == "__main__":
    inputRoot = '/path/to/bids/'
    outRoot = '/path/to/bmps/'
    exe = '/path/to/MRIcroGL'
    if not shutil.which(exe):
        sys.exit("Unable to find exe: "+exe)

    #inputRoot = '/Users/chris/bids/'
    #modalities to deface
    mods =  ["T2w.nii", "T1w.nii", "FLAIR.nii"]
    #mods =  ["FLAIR.nii"]
    subfolders= [f.path for f in os.scandir(inputRoot) if f.is_dir()]
    for subname in list(subfolders):
        sub = Path(subname).stem
        if not sub.startswith("sub-"):
            continue;
        path = subname + '/**/*.nii.gz'
        files = glob.glob(path, recursive=True)
        for m in mods:
            for f in files:
                if m in f:
                    fnm = os.path.basename(f)
                    fnm = os.path.splitext(fnm)[0]
                    if fnm.endswith(".nii"): #file.nii.gz -> file
                        fnm = os.path.splitext(fnm)[0]
                    if fnm.startswith('_') or fnm.startswith('.'):
                        continue
                    bmp = os.path.join(outRoot, fnm + ".png")
                    cmd = exe + ' -s \'import gl\ngl.loadimage("' + f + '")\ngl.mosaic("A 0.5 S 0.5 C 0.5 S R 0.5")\ngl.colorbarposition(0)\ngl.savebmp("' + bmp + '")\ngl.quit()\'\n'
                    os.system(cmd)

@richardbeare
Copy link

Hi Chris,
I've been helping Bonnie and co out with this. I have what I think is a temporary fix, but hardly ideal.
Assuming we want to stick with the MRIcro distributed python, is there a "correct" way of extending that distribution.

For example, glob.py isn't in that distribution, while pathlib.py is. However the pathlib dependencies are not. My hack (for ubuntu 22.04) was to create a minimal python3.7 environment in miniconda and sync the lib folder into Resources/python37/lib/python3.7/. Hardly ideal, but works for the moment.

I couldn't find anything in the sources indicating a correct way of extending the python installation during build time.

Interested in hearing your advice on options.
Thanks

@neurolabusc
Copy link
Contributor

@richardbeare I am not a Python expert. I continue to use the methods I describe above.

@richardbeare
Copy link

Happy to have more of a play - how did you decide on the original content of Resources/python37/ ?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants