1#!/bin/tcsh 2 3# =================================================================== 4# This program calculates where to put the focal point in a montaged 5# image so that the slice-viewing planes are evenly spread out across 6# the volume (well, approximately so). 7# 8# auth: PA Taylor (NIMH, NIH, USA) 9# =================================================================== 10# 11#set set version = "2.0"; set rev_dat = "Dec 19, 2018" 12# + [PT] fix the focal point conditions. 13# 14#set set version = "2.1"; set rev_dat = "Dec 21, 2018" 15# + [PT] re-fix the focal point conditions. 16# 17set set version = "2.2"; set rev_dat = "Jan 25, 2019" 18# + [PT] bux fig: deal with subbrick selectors on inset; 19# thanks again, C. Cunningham for continued patience in 20# bug squashing! 21# 22# =================================================================== 23 24@global_parse `basename $0` "$*" ; if ($status) exit 0 25 26#set version = "0.0"; set rev_dat = "Nov 20, 2018" 27# + this used to be part of @chauffeur_afni, but now is separated 28# into its own separate @djunct_* program 29# 30# ================================================================ 31 32set ulay = "" # dset in question 33set mx = "" # mont dims, x 34set my = "" # mont dims, y 35set OUT_TYPE = "" # do we output ijk or xyz 36 37set coors = ( 0 0 0 ) 38 39# ------------------- process options, a la rr ---------------------- 40 41if ( $#argv == 0 ) goto SHOW_HELP 42 43set ac = 1 44while ( $ac <= $#argv ) 45 # terminal options 46 if ( ("$argv[$ac]" == "-h" ) || ("$argv[$ac]" == "-help" )) then 47 goto SHOW_HELP 48 endif 49 if ( "$argv[$ac]" == "-ver" ) then 50 goto SHOW_VERSION 51 endif 52 53 # ---------- inputs: required --------------- 54 55 if ( "$argv[$ac]" == "-inset" ) then 56 if ( $ac >= $#argv ) goto FAIL_MISSING_ARG 57 @ ac += 1 58 set ulay = "$argv[$ac]" 59 60 else if ( "$argv[$ac]" == "-montx" ) then 61 if ( $ac >= $#argv ) goto FAIL_MISSING_ARG 62 @ ac += 1 63 @ mx = "$argv[$ac]" 64 65 else if ( "$argv[$ac]" == "-monty" ) then 66 if ( $ac >= $#argv ) goto FAIL_MISSING_ARG 67 @ ac += 1 68 @ my = "$argv[$ac]" 69 70 # set type of output: ijk or xyz 71 else if ( "$argv[$ac]" == "-out_ijk" ) then 72 set OUT_TYPE = "IJK" 73 else if ( "$argv[$ac]" == "-out_xyz" ) then 74 set OUT_TYPE = "XYZ" 75 76 else 77 echo "\n\n** ERROR: unexpected option #$ac = '$argv[$ac]'\n\n" 78 goto BAD_EXIT 79 80 endif 81 @ ac += 1 82end 83 84# --------------------------- inputs ------------------------------- 85 86if ( "$ulay" == "" ) then 87 echo "** ERROR: missing input dset! Use '-inset ..'" 88 goto BAD_EXIT 89endif 90 91if ( $mx == "" ) then 92 echo "** ERROR: missing montage dimension!" 93 echo " Use '-montx ..'" 94 goto BAD_EXIT 95endif 96 97if ( $my == "" ) then 98 echo "** ERROR: missing montage dimension!" 99 echo " Use '-monty ..'" 100 goto BAD_EXIT 101endif 102 103if ( $OUT_TYPE == "" ) then 104 echo "** ERROR: missing output type!" 105 echo " Use '-out_ijk' or '-out_xyz'" 106 goto BAD_EXIT 107endif 108 109# ----------------------------- ugh --------------------------------- 110 111# needed to deal with orientation permutability : AIL, LAI, PSR, etc. 112 113set listori = ( 'R' 'L' 'A' 'P' 'I' 'S' ) 114set listind = ( 1 1 2 2 3 3 ) 115 116# just the initializing value 117#set gapord = ( 0 0 0 ) 118 119# ---------------------------- calcs -------------------------------- 120 121# always determine dim from ulay, because that's how montaging works! 122set Dim = `3dinfo -n4 "$ulay"` 123 124# silly stuff to deal with orientation 125set ori = `3dinfo -orient "$ulay"` 126set ori0 = `echo $ori | awk '{print substr($0,1,1)}'` 127set ori1 = `echo $ori | awk '{print substr($0,2,1)}'` 128set ori2 = `echo $ori | awk '{print substr($0,3,1)}'` 129set all_ori = ( $ori0 $ori1 $ori2 ) 130set order = () 131foreach oo ( $all_ori ) 132 foreach i ( `seq 1 1 ${#listori}` ) 133 if ( $oo == "$listori[${i}]" ) then 134 set order = ( $order ${listind[$i]} ) 135 break 136 endif 137 end 138end 139 140# ----------------- quantities related to mont dims ------------------ 141 142# get ceilings of 'montage number + 1', in each direction 143#set xo2 = `echo "scale=2; ( $mx + 1 ) / 2." | bc` 144#set cmx = `echo $xo2 | perl -nl -MPOSIX -e 'print ceil($_);'` 145#set yo2 = `echo "scale=2; ( $my + 1 ) / 2." | bc` 146#set cmy = `echo $yo2 | perl -nl -MPOSIX -e 'print ceil($_);'` 147 148# ------- 1) find zero-based index of montage slices to focus on 149 150# It isn't always just the "middle" one, because in a matrix-like 151# montage, the choice is a bit more complicated. Basically, it is a 152# central slice, in each dimension rounded up. 153# 154# This is also complicated by going back and forth between 0-based and 155# 1-based index numbers. 156 157## [PT: Dec 19, 2018] fix these values, and how they get used just 158## below to find the focal coors in terms of ijk values, which is a 159## little odd, to be honest. 160# zero-based numbers representing the row or col to jump to for the 161# focal slice in the montage. 162if ( `echo "( $mx % 2 )" | bc` == 1 ) then 163 set cmx = `echo "( ( $mx - 1) / 2 )" | bc` 164else 165 set cmx = `echo "( $mx / 2 )" | bc` 166endif 167 168if ( `echo "( $my % 2 )" | bc` == 1 ) then 169 set cmy = `echo "( ( $my - 1) / 2 )" | bc` 170else 171 set cmy = `echo "( $my / 2 )" | bc` 172endif 173 174# total number of panels 175@ tot = $mx * $my 176# which panel is the "focal" one in the montage: 0-based counting for tcsh 177@ hpan = ( ( $cmy ) * $mx ) + $cmx 178#echo "$mx $my $tot" 179#echo "$cmx $cmy $hpan" 180 181# where we go just depends on this 182set gapord = `@djunct_slice_space -nwin $tot -inset "$ulay"` 183 184#set pfrac = `echo "scale=5; ( ( $hpan + 1 ) / ( $tot + 1 ) ) " | bc` # ???? 185#echo "++ pfrac = $pfrac" 186 187# ## [PT: Dec 19, 2018] admittedly, this is an *odd* set of conditions 188# to reposition the centerpoint for the montage. This depends very 189# much on how hpan is defined, above 190foreach i ( `seq 1 1 3` ) 191 set offset = `echo "scale=5; ( $Dim[$i] - ( ( $tot - 1 ) * $gapord[$i] ) ) / 2" | bc` 192 set ccc0 = `echo "scale=5; $offset + ( $hpan * $gapord[$i] ) " | bc` 193 set ccc1 = `echo $ccc0 | perl -nl -MPOSIX -e 'print floor($_);'` 194 #echo OCC $offset $ccc0 $ccc1 $hpan 195 196 # somehow, R&L are just a little bit different 197 if ( ( $all_ori[$i] == 'R' ) ) then 198 set ccc2 = `echo "scale=0; $Dim[$i] - $ccc1 " | bc` 199 else if ( ( $all_ori[$i] == 'L' ) ) then 200 set ccc2 = `echo "scale=0; $ccc1 - 1 " | bc` 201 else if ( ( $all_ori[$i] == 'P' ) || ( $all_ori[$i] == 'S' ) ) then 202 set ccc2 = `echo "scale=0; $Dim[$i] - 1 - $ccc1 " | bc` 203 else 204 set ccc2 = `echo "scale=0; $ccc1 " | bc` 205 endif 206 207 set coors[$i] = `echo $ccc2 | perl -nl -MPOSIX -e 'print floor($_);'` 208end 209 210# ----------------- convert IJK to XYZ ----------------------------- 211 212### Convert ijk -> xyz: the first three elements of $mdumpout are xyz 213# [PT: Jan 29, 2020] Now use a 3dcalc expr in case the ${ulay} dset 214# has RGB type, which would make 3dmaskdump whine (and the value 215# doesn't matter here---we just want ijk->xyz conversion for coords). 216set mdumpout = `3dmaskdump -ibox $coors -noijk -xyz \ 217 "3dcalc -a ${ulay}[0] -expr a -byte"` 218 219if ( "$OUT_TYPE" == "IJK" ) then 220 echo $coors 221else if ( "$OUT_TYPE" == "XYZ" ) then 222 echo $mdumpout[1] $mdumpout[2] $mdumpout[3] 223else 224 echo "** ERROR: bad output type!" 225 echo " This is not an option: '$OUT_TYPE'" 226 goto BAD_EXIT 227endif 228 229goto GOOD_EXIT 230 231# ======================================================================== 232# ======================================================================== 233 234SHOW_HELP: 235cat << EOF 236------------------------------------------------------------------------- 237 238OVERVIEW ~1~ 239 240Just a tiny adjunct program for @chauffeur_afni. 241 242Small program to calculate how to evenly space a certain number of 243slices within each view plane of a dset. Returns three numbers: the 244'delta slices' in the three view planes (in the order of the input 245dset's orientation). 246 247++ constructed by PA Taylor (NIMH, NIH, USA). 248 249# ========================================================================= 250 251RUNNING ~1~ 252 253Inputs ~2~ 254 255 + a volume dset (to have a grid/dimensions) 256 + the montage's x- and y-dimensions 257 + the choice of either IJK or XYZ coordinates to be output 258 259Outputs ~2~ 260 261 + three numbers: either 'i j k' or 'x y z' values. These numbers 262 represent where to tell AFNI to set its crosshairs for a montage. 263 These can be redirected to a file, if so desired for scripting 264 (likely!). 265 266# ========================================================================= 267 268COMMAND OPTIONS ~1~ 269 270-help, -h :see helpfile (here!) 271-ver :see version number 272 273-inset UUU :(req) name of input dset. 274 275-montx MX :(req) montage dimension: number of panels along x-axis 276 (i.e., number of cols) 277 278-monty MY :(req) montage dimension: number of panels along y-axis 279 (i.e., number of rows) 280 281-out_ijk :make program output 'I J K' values. 282-out_xyz :make program output 'X Y Z' values. 283 284EOF 285 286# ---------------------------------------------------------------------- 287 288 goto GOOD_EXIT 289 290SHOW_VERSION: 291 echo "version $version (${rev_dat})" 292 goto GOOD_EXIT 293 294FAIL_MISSING_ARG: 295 echo "** ERROR! Missing an argument after option flag: '$argv[$ac]'" 296 goto BAD_EXIT 297 298BAD_EXIT: 299 exit 1 300 301GOOD_EXIT: 302 exit 0 303