Drive SUMA recording image - Improve image size/ quality?

AFNI version info (afni -ver):
Version AFNI_23.0.07 'Commodus

Hi there,

I have been using drive suma to load up some surfaces and make images of them.

When I record the image, using the following code (below) the images made are not very high quality (they seem grainy/ fuzzy/ not sharp), where they look great on the screen.

DriveSuma \
		-echo_edu -npb $portnum \
		-com viewer_cont -autorecord ${base_dir}/${save_img}.jpg \
		-com viewer_cont -key 'Ctrl+r'

The size of the viewer is 1500 x 800 pixels (see below).

setenv SUMA_Position_Original "0 0  1501 800"

I tried changing image format from .JPG to .PNG to see if this helped, but this did not work, suggesting I am doing something else wrong with recording command. The filenames suggest so also. It's adding it's own date/time name to the one I specified (code above).

Wrote image to /scratch/cvl/uqhdemp1/Data/Columns/derivatives/afni//stats.P002_HW.resamp2nn.surf.blur0.roi_bin_mask.niml.dset.png.A.240612_141959.177.jpg

I'm not sure why there are two // in the filename, as when I echo the variable on it's own I get this:

echo ${base_dir}/${save_img}.png
/scratch/cvl/uqhdemp1/Data/Columns/derivatives/afni/stats.P002_HW.resamp2nn.surf.blur0.roi_bin_mask.niml.dset.png

Aside from whatever error I am making with the saving, I guess there is some compression or something happening? As the size of the images is quite small (244kB), where when I take a screenshot, they are much larger (2.4MB). Is there any way to increase the image quality/ file size?

I tried changing the oversampling up to 4 (option + r), but this did not seem to affect the images I made so I think I was using it incorrectly. I wondered if I should change it in the SUMA environment variable (by setenv SUMA_SnapshotOverSampling "4"?)

In sum, please help me make higher quality images with drive suma.

Thank you for your help,

H

Making the suma view window larger with large values in the last two numbers here:

setenv SUMA_Position_Original "0 0  1501 800"

... should be the way to go.

Here is a driver script I made a while back, which I haven't looked at for a while, but it might help. It uses this suma_MNI_N27 data directory as a reference, being run from just outside it:

#!/bin/tcsh

########################################################################
#
# How to: view volumetric ROIs on SUMA surface and snapshot automatically
#
# Open up AFNI, overlay a value dset, no threshold, project into SUMA,
# rotate the brain to sagittal views for each hemisphere, record jpgs.
#
# v1.0, PA Taylor (NIMH, NIH), Nov 17 2017.
#
########################################################################

# ======================= main user settings =========================
#
# MAIN FILES
# sdir      :loc of SUMA surfs+dsets dir, basically from running FS on
#            MNI template brain
# afni_ulay :'ulay' both for AFNI viewing and as 'sv' volume for SUMA
# afni_ulay :'olay' both for AFNI viewing and projecting onto surface
# olay_brik :which olay brick to display
# suma_spec :file that has all SUMA surfaces with multiple viewing
#            states
# suma_sv   :'surfvol' dset: FOV info needed for AFNI+SUMA to talk, so 
#            we just use the ulay or olay dset.
# ---------------------------------------------------------------------

set here = $PWD

#set sdir = "$HOME/.afni/data/suma_MNI_N27"   
set sdir = "$here/suma_MNI_N27"   

set suma_spec     = "std.141.MNI_N27_both.spec"
set suma_nimldset = "std.141.rh.curv.niml.dset"
set suma_sv       = "MNI_N27_SurfVol.nii"

# what to display, and how
set nimldset_br_i = "0"       # which "brick" of inp dset to display
set nimldset_imin = "-0.25"   # lower value of cbar
set nimldset_imax = "0.25"    # upper value of cbar

set dset_cbar = "Reds_and_Blues_Inv" # which cbar

set nimldset_br_t = "0"       # which "brick" of inp dset to threshold
                              # "-1" turns off thr
set nimldset_tval = "0.10"    # threshold value; "-1" turns off thr

cd $sdir

# -------------------- image file parameters -----------------------

# Saved image naming props: directory and file prefix (latter, taken
# from olay filename here)
set image_dir = "$here/MY_ROI_SURF_IMAGES"        
set image_pre = `basename "$suma_nimldset" ".niml.dset"`

# size of the image window (bigger -> higher res), given as:
#       leftcorner_X  leftcorner_Y  windowwidth_X  windowwith_Y
setenv SUMA_Position_Original "50 50 1500 1500" #"50 50 3500 3500"
#setenv SUMA_Light0Position "10 1 1"

# --------------------- preliminary settings -----------------------

# port number for AFNI+SUMA to talk to each other
set portnum = `afni -available_npb_quiet`

# boring stuff.
setenv AFNI_ENVIRON_WARNINGS       NO
setenv AFNI_PBAR_FULLRANGE         NO
setenv SUMA_DriveSumaMaxCloseWait  20
setenv SUMA_DriveSumaMaxWait       10

setenv SUMA_AutoRecordPrefix "${image_dir}/${image_pre}"
#setenv SUMA_SnapshotOverSampling $OVERSAMP

# ========================= run SUMA ============================

# --------------------- SUMA setup------------------------------

suma                                                            \
    -echo_edu                                                   \
    -npb $portnum                                               \
    -niml                                                       \
    -spec  $suma_spec                                           \
    -sv    $suma_sv     &

echo "++ more sleepy time..."
sleep 3

# for Macness (or madness, or the same thing...)
DriveSuma                                            \
    -echo_edu                                        \
    -npb $portnum                                    \
    -com surf_cont -view_surf_cont y

echo "++ more sleepy time..."
sleep 2

DriveSuma                                            \
    -echo_edu                                        \
    -npb $portnum                                    \
    -com surf_cont -load_dset $suma_nimldset         \
    -com surf_cont -switch_cmap "$dset_cbar"         \
    -view_surf_cont y

# set brick of dset to look at
# set range of values for cbar
# set brick of dset to thr at
# set threshold value
DriveSuma                                            \
    -echo_edu                                        \
    -npb $portnum                                    \
    -com surf_cont -I_sb  "$nimldset_br_i"           \
    -I_range "$nimldset_imin" "$nimldset_imax"       \
    -T_sb   "$nimldset_br_t"                         \
    -T_val  "$nimldset_tval"

# '.' keypress to go through spec file list to surf type 
#     we want for image
# brain looks left.
DriveSuma                                              \
    -echo_edu                                          \
    -npb $portnum                                      \
    -com viewer_cont -key '.' -key '.'                 \
    -com  viewer_cont  -key ctrl+left 

sleep 3

# In order, turn *OFF* visibility of the:  
#    crosshair, selector node, selector faceset, and label
DriveSuma                                              \
    -echo_edu                                          \
    -npb $portnum                                      \
    -com viewer_cont -key 'F3' -key 'F4' -key 'F5' -key 'F9'

# Sagittal profile,  SNAP
DriveSuma                                              \
    -npb $portnum                                      \
    -com viewer_cont -key 'Ctrl+left'                  \
    -com viewer_cont -key 'Ctrl+r'

sleep 1

# same hemi, SNAP
DriveSuma                                              \
    -npb $portnum                                      \
    -com viewer_cont -key 'Ctrl+right'                 \
    -com viewer_cont -key 'Ctrl+r'

sleep 1

# front cor profile, SNAP
DriveSuma                                              \
    -npb $portnum                                      \
    -com viewer_cont -key 'Ctrl+up'                    \
    -com viewer_cont -key 'Ctrl+r'

sleep 1

# back cor profile, SNAP
DriveSuma                                              \
    -npb $portnum                                      \
    -com viewer_cont -key 'Ctrl+down'                  \
    -com viewer_cont -key 'Ctrl+r'

sleep 1

# Close everything down!  Optionally, can leave AFNI+SUMA running, if
# you preferred.
#@Quiet_Talkers -npb_val $portnum


echo "++ DONE!"

If you change the size of the SUMA_Position_Original numbers, you get a larger screenshot (more pixels per image); when you shrink that to comparable sizes in your image, the larger one has effectively higher res. I just verified that works, trying either 500x500 or 1500x1500. The number of pixels in the corresponding outputs were 496x467 and 1496x1351, respectively:
std.141.rh.curv.A.240612_071932.506

--pt

Hi PT,

Thank you for your reply and your code.

I just tried your fix, running my code with:
setenv SUMA_Position_Original "0 0 1501 1100"

Then:
setenv SUMA_Position_Original "0 0 3002 1706"

I ended up with the same size file (both 215kB) but I now think that it might be because my view file is changing the window size/ resolution/ something. I think this because I saw my SUMA window become large while everything was initially booting up, then shrink again to the same size both times - presumably my saved view size, which loaded later on.

Is there a way to keep the positioning of my original saved views (as they are centred on my ROI for each participant), but make the image higher res/ bigger?

As an additional question, I don't know much about environment variables, should my suma -update_env go before or after I set my environment variables with setenv (or does it not matter)?

Sorry, my code is a bit long and clunky, it grew out of my control :slight_smile:

#!/bin/tcsh -xef

## Set/ change some SUMA environment variables

# Update - fixes issues with driving SUMA - should go after stuff below??
suma -update_env

# Added from forum post
setenv AFNI_ENVIRON_WARNINGS       NO
setenv AFNI_PBAR_FULLRANGE         NO
setenv SUMA_DriveSumaMaxCloseWait  20
setenv SUMA_DriveSumaMaxWait       10

# Size of the viewer window (bigger -> higher res), given as:leftcorner_X  leftcorner_Y  windowwidth_X  windowwith_Y
# ... and a small quirk: the width is tweaked in a DriveSuma command below to have width=800 (instead of 801), 
# to refresh the viewer, so the brain is centered.  The exact numbers don't matter, but if the viewer size is *only* set below, suma controller blocks view of the viewer.
# setenv SUMA_Position_Original "0 0  1501 1100" # what I originally used to use on work mac - but may have used the below as width was not wide enough to allow 1100
# setenv SUMA_Position_Original "0 0  1501 853" # width on work comp is actually 853
# setenv SUMA_Position_Original "0 0  3002 2200" # Double res for what I used to use
setenv SUMA_Position_Original "0 0  3002 1706" # Might be what I actually want to keep aspect ratio at bigger image resolution

#setenv SUMA_Light0Position "10 1 1"

# Moved some setenv stuff related to recording down as was needed in script order


# CHECK
set get = 1 # Which number participant (in order on list below); 7 = P008_AY; 11 = P012_AY
set ii = 5 # Which image to load: 1 = fingertips; 2 = columns; 3 = (binarised) columns; 4 = (binarised) columns intersect maps; 5 = (binarised) laminar columns maps; 6 = P012 AY 6/12 runs intersection; 7 = P012 AY s1 6x s2 6 intersection

# Set depth num - not used unless ii == 5, but needed for load
set num = 0.0

# Automatically add session append if needed
if ( $get == 11 ) then
	set append_file = .12runs
	set append_sub = 2
else if ($get == 7) then
	set append_file = 
	set append_sub = 1
else
	set append_file = 
	set append_sub = 
endif

set surfview = 3 # 1 = pial; 2 = inf15k; 3 = sphere
set makeortake = 3 # 1 = make; 2 = take image; 3 = both (works like 1 but adds take image on the end)

if ( $surfview == 1 ) then
	if ( $makeortake == 1 || $makeortake == 3 ) then
		# Load suma
		set withload = 1 # 1 = Load suma from start
	else if ( $makeortake == 2 ) then
		set withload = 2
	endif
else
	set withload = 2 # 2 = suma already open
endif
set withload = 1 # Reset if needed

set view = 3 # Use 1 = canonical orientation; 2 = view of sub before; 3 = sub themselves


# Derive sub things (AY = 7; AY2 = 11)
set subs_c = ( "P002_HW" "P003_GS" "P004_LF" "P005_RG" "P006_AF" "P007_HB" "P008_AY" "P009_ZQ" "P010_SB" "P011_AV" "P012_AY")
set subs_f = ( "P009_HW" "P013_GS" "P005_LF" "P003_RG" "P004_AF" "P008_HB" "P007_AY" "P010_ZQ" "P011_SB" "P006_AV" "P007_AY")
set sub_c = $subs_c[$get]
set sub_f = $subs_f[$get]

set sub_num_c = `echo $sub_c | awk '{print substr($0,1,4)}'`
set sub_num_f = `echo $sub_f | awk '{print substr($0,1,4)}'`
set init = `echo $sub_c | awk '{print substr($0,6,7)}'`

@ get2 = $get - 1
set init_b4 = $subs_c[$get2]
set init_b4 = `echo $init_b4 | awk '{print substr($0,6,7)}'`

# Derive view things
if ( $surfview == 1 ) then
	set inflation_name = pial
else if ( $surfview == 2 ) then
	set inflation_name = inf15k
else if ( $surfview == 3 ) then
	set inflation_name = sphere
else
endif

# port number for AFNI+SUMA to talk to each other - manually set to 0 so works when not loading for first time - do not change
set portnum = 0
# set portnum = `afni -available_npb_quiet`

# directories
set base_dir = "/scratch/cvl/uqhdemp1/Data/Columns/derivatives/afni"
set sub_dir = "$base_dir/P00_${init}${append_sub}_antsTemp.dense.fs"


# set up datasets you want to look at
set all_dset = ( "$sub_dir/vis/pb10.${sub_num_f}_${init}.rall.scale.trim.resamp2nn.surf.blur0.3dD_sine.DEL.niml.dset" \
		"$sub_dir/vis/stats.${sub_num_c}_${init}.resamp2nn.surf.blur0.roi.niml.dset" \
		"$base_dir/Binarised_maps/stats.${sub_num_c}_${init}.resamp2nn.surf.blur0.roi${append_file}_bin_mask.niml.dset" \
		"$base_dir/Intersection_maps/stats.${sub_num_c}_${init}.resamp2nn.surf.blur0.roi_bin_mask_statsINTERSECT${append_file}.niml.dset" \
		"$base_dir/Binarised_maps/Laminar/stats.${sub_num_c}_${init}.resamp2nn.equivol${num}.surf.blur0.padded.roi_bin_mask.niml.dset" \
		"$base_dir/Intersection_maps/stats.${sub_num_c}_${init}.resamp2nn.surf.blur0.roi${append_file}_bin_mask_statsINTERSECT.niml.dset" \
		"$base_dir/Intersection_maps/stats.${sub_num_c}_${init}.resamp2nn.surf.blur0.roi_bin_mask_statsINTERSECT.6runs.s1s2.niml.dset" )

set all_cbar = ( "afni_n20" \
					"afni_n6" \
					"Spectrum:red_to_blue+gap" \
					"Spectrum:red_to_blue+gap" \
					"Spectrum:red_to_blue+gap" \
					"Spectrum:red_to_blue+gap" \
					"Spectrum:red_to_blue+gap" )

set dset_ii = ${all_dset[${ii}]}
set cbar_ii = ${all_cbar[${ii}]}

set spec = "P00_${init}_antsTemp.dense.fs_lh.spec"
set sv = "${init}_columns_SurfVol_Alnd_Exp+orig"


# Set up stuff for recording
# Get save image name - these two below do the same thing
# set img_pre = `echo $dset_ii | awk -F/ '{print $NF}'`
set img_pre = `basename "$dset_ii" ".niml.dset"`
set img_pre = ${img_pre}_${inflation_name}

# SUMA_AutoRecordPrefix (env): Prefix for autorecord (suma’s Ctrl+R) files. FreeSurfer states should not be sent to AFNI. Add a path if you want the files to endup in a particular directory. You can also add an extension to prefix to specify the output type. Choose from .jpg, .ppm, or .1D . The fallback type is .jpg
setenv SUMA_AutoRecordPrefix "${base_dir}/${img_pre}"

# Increase the resolution of images recorded with ‘r’ button. Increase is done by taking multiple shots that once stitched together form a high-resolution image. The maximum resolution is set by the GL_MAX_VIEWPORT_DIMS of your graphics card. I have 4096 pixels. If you exceed this number, SUMA will make adjustments automatically. Assemble images with program imcat.
# setenv SUMA_SnapshotOverSampling "4"


# # If loading from the start
if ( $withload == 1 ) then

	# Change dir to data
	cd $sub_dir/SUMA

	# open up surfaces - columns image can be used for fingertips and columns
	suma -echo_edu -npb $portnum \
		-niml \
		-spec $spec \
		-sv $sv &

	sleep 45

	# Turn *OFF* visibility of the crosshair, selector node, selector faceset, and label
	DriveSuma -echo_edu -npb $portnum \
		-com viewer_cont -key 'F3' -key 'F4' -key 'F5' -key 'F9'
	
	sleep 1
# End of withload loop
endif


# Open surface controller
DriveSuma -echo_edu -npb $portnum \
	-com surf_cont -view_surf_cont y

sleep 2

# Open dset, and set colorbar
DriveSuma -echo_edu -npb $portnum \
    -com surf_cont -load_dset ${dset_ii} \
	-com surf_cont -switch_cmap ${cbar_ii}

sleep 3


# Open old roi if it exists, and set opacity/disp mode/colorbar (could be put into loop above with another array for "Dsp" opts)
set roi_file = fMap_Q001_postAl.niml.dset
if ( -e $sub_dir/vis/$roi_file) then
	DriveSuma -echo_edu -npb $portnum \
		-com object_cont -load_dset $sub_dir/vis/$roi_file \
		-com object_cont -1_only n \
		-com object_cont -Dsp Con
endif

sleep 1


# Open correct inflation
if ( $withload == 1 ) then
	if ($surfview == 1) then

		# Pial
		DriveSuma -echo_edu -npb $portnum \
			-com viewer_cont -key '.'

	else if ($surfview == 2) then

		# Inf15k
		if ($withload == 1) then
			DriveSuma -echo_edu -npb $portnum \
				-com viewer_cont -key ','
		else
			DriveSuma -echo_edu -npb $portnum \
				-com viewer_cont -key:r2 ','
		endif

	else if ($surfview == 3) then

		# Sphere
			if ($withload == 1) then
				DriveSuma -echo_edu -npb $portnum \
					-com viewer_cont -key:r4 ','
			else
				DriveSuma -echo_edu -npb $portnum \
					-com viewer_cont -key:r3 ','
			endif

	endif

	sleep 5


	# Change to desired orientation
	if ( $view == 1 ) then
	
		# Use canonical orientation
		if ( $surfview == 1 ) then
			# Pial
			DriveSuma -echo_edu -npb $portnum \
				-com viewer_cont -key 'Ctrl+left' \
				-com viewer_cont -key:r9 'Z'
		else if ( $surfview == 2 ) then
			# Inf15k
			DriveSuma -echo_edu -npb $portnum \
				-com viewer_cont -key 'Ctrl+left' \
				-com viewer_cont -key:r11 'Z'
		else if ( $surfview == 3 ) then
			# Sphere
			DriveSuma -echo_edu -npb $portnum \
		 	-com viewer_cont -key:r5 'right' \
		 	-com viewer_cont -key:r3 'up' \
			-com viewer_cont -key:r11 'Z'
		endif

	else if ( $view == 2 ) then

		# Use sub b4 OR view b4 (if inf15k)
		if ( $surfview == 2 ) then
			DriveSuma -echo_edu -npb $portnum \
		 		-com viewer_cont -load_view $base_dir/Views/${init}_pial.niml.vvs
		else
			DriveSuma -echo_edu -npb $portnum \
		 		-com viewer_cont -load_view $base_dir/Views/${init_b4}_${inflation_name}.niml.vvs
		endif

	else if ( $view == 3 ) then

		# Use sub themselves
		DriveSuma -echo_edu -npb $portnum \
		 	-com viewer_cont -load_view $base_dir/Views/${init}_${inflation_name}.niml.vvs

	endif

	# Turn off background attenutation (so can't see convexity through functional data)
	DriveSuma -echo_edu -npb $portnum \
				-com viewer_cont -key 'a'


	# # Manual stuff for fingertip maps=
	# Change T (thresh) to 2: corr coeff
	# Turn sym (symmetrical) off
	# Set I (intensity) range to 0 48
	# Drag slider to q = .05

# End of makeortake if
endif


# Change background colour to white - do at end as it gets reset in sphere
DriveSuma -echo_edu -npb $portnum \
	-com viewer_cont -bkg_col 1 1 1


if ( $makeortake == 2 || $makeortake == 3 ) then
	# Take image
	DriveSuma \
		-echo_edu -npb $portnum \
		-com viewer_cont -key 'Ctrl+r'
endif

Also my filenames still look a bit odd (with some random letters/ datetime letters on the end), am I setting the recording name incorrectly?

The bit after sphere should not be there

Example: stats.P002_HW.resamp2nn.equivol0.0.surf.blur0.padded.roi_bin_mask_sphere.A.240801_145315.268.jpg

Howdy-

This command only needs to be run once, at installation, to populate the SUMA settings file ~/.sumarc:

suma -update_env

I see that running it again later doesn't reset all values, but I still think I would not keep it in a script.

I tried running the script I initially posted by changing the image size via setenv SUMA_Positiion_Original, and that did change the output file size and image size. Note that this script is creating JPGs, which are inherently compressed, so doubling the image dimensions on the screen is not expected to quadruple the file size; for my example, the file size increases were moderate.

Indeed, as you suggest, loading the "view file" later on (i.e., one of your *.vvs file) is going to reset the image window size. The view information is the meta information about how you setup your SUMA window: size of panel, angle of brain, zooming in/out, etc. So, that is effectively making your SUMa window erase/ignore your earlier window size.

To drive respositioning the brain, you can use Shift+up, Shift+left, etc. to translate the brain up, left, etc. So, for example:

DriveSuma                                              \
    -npb $portnum                                      \
    -com viewer_cont -key 'Ctrl+up'  -key 'Ctrl+up'   -key 'Ctrl+left'    

... or, with repeat modifer:

DriveSuma                                              \
    -npb $portnum                                      \
    -com viewer_cont -key:r2 'Ctrl+up'  -key 'Ctrl+left'    

-pt

Hi PT,

Thanks for your continued help and patience on this.

Since the views are specific for each person I just re-sized the window to the max for my screen (3429 x 1237) and saved them again. By doing so, I have increased the size from 272kB to 485kB, which is still very small, considering the pixel dimensions and that when I take a screenshot I get images of about 1.9MB.

Do you think it could be the image are small because of jpg compression?
Would a different file type work, like .png?

I have tried changing the extension of my filename to .png, but it does not change from jpg. I think something is going wrong with my settings for auto record as I get some automatic text appended to the end of my filename like "dset.A.240815_112354.jpg" - where everything after the A is not supposed to be there

Here are my save commands:

set img_pre = basename "$dset_ii" ".niml.dset"
setenv SUMA_AutoRecordPrefix "{base_dir}/{img_pre}"

Hi-

I don't think that just because the JPG file sizes are different there is necessarily a problem. They might have different compression modes. It sounds like you were getting appropriate file size increase---since the background is largely monochrome, and the images are just scaling up in size, I might not expect a huge file size increase when using the same saving/compression mechanism. It could be that the screenshot mechanism itself is different. Are the images fine?

For the filename: there is the prefix (like "dset.A"), and then a timestamp (like "240815_112354", which means you took the snapshot in 2024, in the 8th month, fifteenth day, at 11:23:54am). You are able to change the prefix part, but the time stamp will always be there. That is what will help differentiate different images snapped in the same script, typically. If you wanted, and there is only 1 script saving images to a directory at a time, you could use the shell listing functionality to get the latest file, which should be something like:

set my_last_img = `ls -1t | head -n 1`

# or 
set my_last_img = `ls -1t dset.A.*jpg | head -n 1`

... and then you could rename the whole thing with mv ${my_last_img} NEW_NAME.jpg.

--pt